diff options
Diffstat (limited to 'driver')
165 files changed, 0 insertions, 41777 deletions
diff --git a/driver/accel_bma2x2.c b/driver/accel_bma2x2.c deleted file mode 100644 index 9a63bdc1ba..0000000000 --- a/driver/accel_bma2x2.c +++ /dev/null @@ -1,317 +0,0 @@ -/* 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. - */ - -/* - * Bosch Accelerometer driver for Chrome EC - * - * Supported: BMA255 - */ - -#include "accelgyro.h" -#include "common.h" -#include "console.h" -#include "driver/accel_bma2x2.h" -#include "i2c.h" -#include "math_util.h" -#include "spi.h" -#include "task.h" -#include "util.h" - -#define CPUTS(outstr) cputs(CC_ACCEL, outstr) -#define CPRINTF(format, args...) cprintf(CC_ACCEL, format, ## args) - -/* Number of times to attempt to enable sensor before giving up. */ -#define SENSOR_ENABLE_ATTEMPTS 5 - -/** - * Read register from accelerometer. - */ -static inline int raw_read8(const int port, const uint16_t i2c_addr_flags, - const int reg, int *data_ptr) -{ - return i2c_read8(port, i2c_addr_flags, reg, data_ptr); -} - -/** - * Write register from accelerometer. - */ -static inline int raw_write8(const int port, const uint16_t i2c_addr_flags, - const int reg, int data) -{ - return i2c_write8(port, i2c_addr_flags, reg, data); -} - -static int set_range(const struct motion_sensor_t *s, int range, int rnd) -{ - int ret, range_val, reg_val, range_reg_val; - struct accelgyro_saved_data_t *data = s->drv_data; - - range_val = BMA2x2_RANGE_TO_REG(range); - if ((BMA2x2_RANGE_TO_REG(range_val) < range) && rnd) - range_val = BMA2x2_RANGE_TO_REG(range * 2); - - mutex_lock(s->mutex); - - /* Determine the new value of control reg and attempt to write it. */ - ret = raw_read8(s->port, s->i2c_spi_addr_flags, - BMA2x2_RANGE_SELECT_ADDR, &range_reg_val); - if (ret != EC_SUCCESS) { - mutex_unlock(s->mutex); - return ret; - } - reg_val = (range_reg_val & ~BMA2x2_RANGE_SELECT_MSK) | range_val; - ret = raw_write8(s->port, s->i2c_spi_addr_flags, - BMA2x2_RANGE_SELECT_ADDR, reg_val); - - /* If successfully written, then save the range. */ - if (ret == EC_SUCCESS) - data->range = BMA2x2_REG_TO_RANGE(range_val); - - mutex_unlock(s->mutex); - - return ret; -} - -static int get_range(const struct motion_sensor_t *s) -{ - struct accelgyro_saved_data_t *data = s->drv_data; - - return data->range; -} - -static int get_resolution(const struct motion_sensor_t *s) -{ - return BMA2x2_RESOLUTION; -} - -static int set_data_rate(const struct motion_sensor_t *s, int rate, int rnd) -{ - int ret, odr_val, odr_reg_val, reg_val; - struct accelgyro_saved_data_t *data = s->drv_data; - - odr_val = BMA2x2_BW_TO_REG(rate); - if ((BMA2x2_REG_TO_BW(odr_val) < rate) && rnd) - odr_val = BMA2x2_BW_TO_REG(rate * 2); - - mutex_lock(s->mutex); - - /* Determine the new value of control reg and attempt to write it. */ - ret = raw_read8(s->port, s->i2c_spi_addr_flags, - BMA2x2_BW_SELECT_ADDR, &odr_reg_val); - if (ret != EC_SUCCESS) { - mutex_unlock(s->mutex); - return ret; - } - reg_val = (odr_reg_val & ~BMA2x2_BW_MSK) | odr_val; - /* Set output data rate. */ - ret = raw_write8(s->port, s->i2c_spi_addr_flags, - BMA2x2_BW_SELECT_ADDR, reg_val); - - /* If successfully written, then save the new data rate. */ - if (ret == EC_SUCCESS) - data->odr = BMA2x2_REG_TO_BW(odr_val); - - mutex_unlock(s->mutex); - return ret; -} - -static int get_data_rate(const struct motion_sensor_t *s) -{ - struct accelgyro_saved_data_t *data = s->drv_data; - - return data->odr; -} - -static int set_offset(const struct motion_sensor_t *s, const int16_t *offset, - int16_t temp) -{ - int i, ret; - - /* temperature is ignored */ - /* Offset from host is in 1/1024g, 1/128g internally. */ - for (i = X; i <= Z; i++) { - ret = raw_write8(s->port, s->i2c_spi_addr_flags, - BMA2x2_OFFSET_X_AXIS_ADDR + i, offset[i] / 8); - if (ret) - return ret; - } - return EC_SUCCESS; -} - -static int get_offset(const struct motion_sensor_t *s, int16_t *offset, - int16_t *temp) -{ - int i, val, ret; - - for (i = X; i <= Z; i++) { - ret = raw_read8(s->port, s->i2c_spi_addr_flags, - BMA2x2_OFFSET_X_AXIS_ADDR + i, &val); - if (ret) - return ret; - offset[i] = (int8_t)val * 8; - } - *temp = EC_MOTION_SENSE_INVALID_CALIB_TEMP; - return EC_SUCCESS; -} - -static int read(const struct motion_sensor_t *s, intv3_t v) -{ - uint8_t acc[6]; - int ret, i; - - /* Read 6 bytes starting at X_AXIS_LSB. */ - mutex_lock(s->mutex); - ret = i2c_read_block(s->port, s->i2c_spi_addr_flags, - BMA2x2_X_AXIS_LSB_ADDR, acc, 6); - mutex_unlock(s->mutex); - - if (ret != EC_SUCCESS) - return ret; - - /* - * Convert acceleration to a signed 16-bit number. Note, based on - * the order of the registers: - * - * acc[0] = X_AXIS_LSB -> bit 7~4 for value, bit 0 for new data bit - * acc[1] = X_AXIS_MSB - * acc[2] = Y_AXIS_LSB -> bit 7~4 for value, bit 0 for new data bit - * acc[3] = Y_AXIS_MSB - * acc[4] = Z_AXIS_LSB -> bit 7~4 for value, bit 0 for new data bit - * acc[5] = Z_AXIS_MSB - */ - for (i = X; i <= Z; i++) - v[i] = (((int8_t)acc[i * 2 + 1]) << 8) | (acc[i * 2] & 0xf0); - rotate(v, *s->rot_standard_ref, v); - - return EC_SUCCESS; -} - -static int perform_calib(const struct motion_sensor_t *s, int enable) -{ - int ret, val, status, rate, range, i; - timestamp_t deadline; - - if (!enable) - return EC_SUCCESS; - - ret = raw_read8(s->port, s->i2c_spi_addr_flags, - BMA2x2_OFFSET_CTRL_ADDR, &val); - if (ret) - return ret; - if (!(val & BMA2x2_OFFSET_CAL_READY)) - return EC_ERROR_ACCESS_DENIED; - - rate = get_data_rate(s); - range = get_range(s); - /* - * Temporary set frequency to 100Hz to get enough data in a short - * period of time. - */ - set_data_rate(s, 100000, 0); - set_range(s, 2, 0); - - /* We assume the device is laying flat for calibration */ - if (s->rot_standard_ref == NULL || - (*s->rot_standard_ref)[2][2] > INT_TO_FP(0)) - val = BMA2x2_OFC_TARGET_PLUS_1G; - else - val = BMA2x2_OFC_TARGET_MINUS_1G; - val = ((BMA2x2_OFC_TARGET_0G << BMA2x2_OFC_TARGET_AXIS(X)) | - (BMA2x2_OFC_TARGET_0G << BMA2x2_OFC_TARGET_AXIS(Y)) | - (val << BMA2x2_OFC_TARGET_AXIS(Z))); - raw_write8(s->port, s->i2c_spi_addr_flags, - BMA2x2_OFC_SETTING_ADDR, val); - - for (i = X; i <= Z; i++) { - val = (i + 1) << BMA2x2_OFFSET_TRIGGER_OFF; - raw_write8(s->port, s->i2c_spi_addr_flags, - BMA2x2_OFFSET_CTRL_ADDR, val); - /* - * The sensor needs 16 samples. At 100Hz/10ms, it needs 160ms to - * complete. Set 400ms to have some margin. - */ - deadline.val = get_time().val + 400 * MSEC; - do { - if (timestamp_expired(deadline, NULL)) { - ret = EC_RES_TIMEOUT; - goto end_perform_calib; - } - msleep(50); - ret = raw_read8(s->port, s->i2c_spi_addr_flags, - BMA2x2_OFFSET_CTRL_ADDR, &status); - if (ret != EC_SUCCESS) - goto end_perform_calib; - } while ((status & BMA2x2_OFFSET_CAL_READY) == 0); - } - -end_perform_calib: - set_range(s, range, 0); - set_data_rate(s, rate, 0); - return ret; -} - -static int init(const struct motion_sensor_t *s) -{ - int ret = 0, tries = 0, val, reg, reset_field; - - ret = raw_read8(s->port, s->i2c_spi_addr_flags, - BMA2x2_CHIP_ID_ADDR, &val); - if (ret) - return EC_ERROR_UNKNOWN; - - if (val != BMA255_CHIP_ID_MAJOR) - return EC_ERROR_ACCESS_DENIED; - - /* Reset the chip to be in a good state */ - reg = BMA2x2_RST_ADDR; - reset_field = BMA2x2_CMD_SOFT_RESET; - - mutex_lock(s->mutex); - - ret = raw_read8(s->port, s->i2c_spi_addr_flags, reg, &val); - if (ret != EC_SUCCESS) { - mutex_unlock(s->mutex); - return ret; - } - val |= reset_field; - ret = raw_write8(s->port, s->i2c_spi_addr_flags, reg, val); - if (ret != EC_SUCCESS) { - mutex_unlock(s->mutex); - return ret; - } - - /* The SRST will be cleared when reset is complete. */ - do { - ret = raw_read8(s->port, s->i2c_spi_addr_flags, reg, &val); - - /* Reset complete. */ - if ((ret == EC_SUCCESS) && !(val & reset_field)) - break; - - /* Check for tires. */ - if (tries++ > SENSOR_ENABLE_ATTEMPTS) { - ret = EC_ERROR_TIMEOUT; - mutex_unlock(s->mutex); - return ret; - } - msleep(1); - } while (1); - mutex_unlock(s->mutex); - - return sensor_init_done(s); -} - -const struct accelgyro_drv bma2x2_accel_drv = { - .init = init, - .read = read, - .set_range = set_range, - .get_range = get_range, - .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 = perform_calib, -}; diff --git a/driver/accel_bma2x2.h b/driver/accel_bma2x2.h deleted file mode 100644 index 4b86161dd2..0000000000 --- a/driver/accel_bma2x2.h +++ /dev/null @@ -1,165 +0,0 @@ -/* 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. - */ - -/* BMA2x2 gsensor module for Chrome EC */ - -#ifndef __CROS_EC_ACCEL_BMA2x2_H -#define __CROS_EC_ACCEL_BMA2x2_H - -extern const struct accelgyro_drv bma2x2_accel_drv; - -/* I2C ADDRESS DEFINITIONS */ -/* The following definition of I2C address is used for the following sensors -* BMA255 -* BMA355 -* BMA280 -* BMA282 -* BMA223 -* BMA254 -* BMA284 -* BMA250E -* BMA222E -*/ -#define BMA2x2_I2C_ADDR1_FLAGS 0x18 -#define BMA2x2_I2C_ADDR2_FLAGS 0x19 - -/* The following definition of I2C address is used for the following sensors -* BMC150 -* BMC056 -* BMC156 -*/ -#define BMA2x2_I2C_ADDR3_FLAGS 0x10 -#define BMA2x2_I2C_ADDR4_FLAGS 0x11 - -/*** Chip-specific registers ***/ -/* REGISTER ADDRESS DEFINITIONS */ -#define BMA2x2_EEP_OFFSET 0x16 -#define BMA2x2_IMAGE_BASE 0x38 -#define BMA2x2_IMAGE_LEN 22 -#define BMA2x2_CHIP_ID_ADDR 0x00 -#define BMA255_CHIP_ID_MAJOR 0xfa - -/* DATA ADDRESS DEFINITIONS */ -#define BMA2x2_X_AXIS_LSB_ADDR 0x02 -#define BMA2x2_X_AXIS_MSB_ADDR 0x03 -#define BMA2x2_Y_AXIS_LSB_ADDR 0x04 -#define BMA2x2_Y_AXIS_MSB_ADDR 0x05 -#define BMA2x2_Z_AXIS_LSB_ADDR 0x06 -#define BMA2x2_Z_AXIS_MSB_ADDR 0x07 -#define BMA2x2_TEMP_ADDR 0x08 - -/* STATUS ADDRESS DEFINITIONS */ -#define BMA2x2_STAT1_ADDR 0x09 -#define BMA2x2_STAT2_ADDR 0x0A -#define BMA2x2_STAT_TAP_SLOPE_ADDR 0x0B -#define BMA2x2_STAT_ORIENT_HIGH_ADDR 0x0C -#define BMA2x2_STAT_FIFO_ADDR 0x0E -#define BMA2x2_RANGE_SELECT_ADDR 0x0F -#define BMA2x2_RANGE_SELECT_MSK 0x0F -#define BMA2x2_RANGE_2G 3 -#define BMA2x2_RANGE_4G 5 -#define BMA2x2_RANGE_8G 8 -#define BMA2x2_RANGE_16G 12 - -#define BMA2x2_RANGE_TO_REG(_range) \ - ((_range) < 8 ? BMA2x2_RANGE_2G + ((_range) / 4) * 2 : \ - BMA2x2_RANGE_8G + ((_range) / 16) * 4) - -#define BMA2x2_REG_TO_RANGE(_reg) \ - ((_reg) < BMA2x2_RANGE_8G ? 2 + (_reg) - BMA2x2_RANGE_2G : \ - 8 + ((_reg) - BMA2x2_RANGE_8G) * 2) - -#define BMA2x2_BW_SELECT_ADDR 0x10 -#define BMA2x2_BW_MSK 0x1F -#define BMA2x2_BW_7_81HZ 0x08 /* LowPass 7.81HZ */ -#define BMA2x2_BW_15_63HZ 0x09 /* LowPass 15.63HZ */ -#define BMA2x2_BW_31_25HZ 0x0A /* LowPass 31.25HZ */ -#define BMA2x2_BW_62_50HZ 0x0B /* LowPass 62.50HZ */ -#define BMA2x2_BW_125HZ 0x0C /* LowPass 125HZ */ -#define BMA2x2_BW_250HZ 0x0D /* LowPass 250HZ */ -#define BMA2x2_BW_500HZ 0x0E /* LowPass 500HZ */ -#define BMA2x2_BW_1000HZ 0x0F /* LowPass 1000HZ */ - -#define BMA2x2_BW_TO_REG(_bw) \ - ((_bw) < 125000 ? BMA2x2_BW_7_81HZ + __fls((_bw) / 7810) : \ - BMA2x2_BW_125HZ + __fls((_bw) / 125000)) - -#define BMA2x2_REG_TO_BW(_reg) \ - ((_reg) < BMA2x2_BW_125HZ ? 7810 << ((_reg) - BMA2x2_BW_7_81HZ) : \ - 125000 << ((_reg) - BMA2x2_BW_125HZ)) - -#define BMA2x2_MODE_CTRL_ADDR 0x11 -#define BMA2x2_LOW_NOISE_CTRL_ADDR 0x12 -#define BMA2x2_DATA_CTRL_ADDR 0x13 -#define BMA2x2_RST_ADDR 0x14 -#define BMA2x2_CMD_SOFT_RESET 0xb6 - -/* INTERRUPT ADDRESS DEFINITIONS */ -#define BMA2x2_INTR_ENABLE1_ADDR 0x16 -#define BMA2x2_INTR_ENABLE2_ADDR 0x17 -#define BMA2x2_INTR_SLOW_NO_MOTION_ADDR 0x18 -#define BMA2x2_INTR1_PAD_SELECT_ADDR 0x19 -#define BMA2x2_INTR_DATA_SELECT_ADDR 0x1A -#define BMA2x2_INTR2_PAD_SELECT_ADDR 0x1B -#define BMA2x2_INTR_SOURCE_ADDR 0x1E -#define BMA2x2_INTR_SET_ADDR 0x20 -#define BMA2x2_INTR_CTRL_ADDR 0x21 - -/* FEATURE ADDRESS DEFINITIONS */ -#define BMA2x2_LOW_DURN_ADDR 0x22 -#define BMA2x2_LOW_THRES_ADDR 0x23 -#define BMA2x2_LOW_HIGH_HYST_ADDR 0x24 -#define BMA2x2_HIGH_DURN_ADDR 0x25 -#define BMA2x2_HIGH_THRES_ADDR 0x26 -#define BMA2x2_SLOPE_DURN_ADDR 0x27 -#define BMA2x2_SLOPE_THRES_ADDR 0x28 -#define BMA2x2_SLOW_NO_MOTION_THRES_ADDR 0x29 -#define BMA2x2_TAP_PARAM_ADDR 0x2A -#define BMA2x2_TAP_THRES_ADDR 0x2B -#define BMA2x2_ORIENT_PARAM_ADDR 0x2C -#define BMA2x2_THETA_BLOCK_ADDR 0x2D -#define BMA2x2_THETA_FLAT_ADDR 0x2E -#define BMA2x2_FLAT_HOLD_TIME_ADDR 0x2F -#define BMA2x2_SELFTEST_ADDR 0x32 -#define BMA2x2_EEPROM_CTRL_ADDR 0x33 -#define BMA2x2_SERIAL_CTRL_ADDR 0x34 - -/* OFFSET ADDRESS DEFINITIONS */ -#define BMA2x2_OFFSET_CTRL_ADDR 0x36 -#define BMA2x2_OFFSET_RESET 0x80 -#define BMA2x2_OFFSET_TRIGGER_OFF 5 -#define BMA2x2_OFFSET_TRIGGER_MASK (0x3 << BMA2x2_OFFSET_TRIGGER_OFF) -#define BMA2x2_OFFSET_CAL_READY 0x10 - -#define BMA2x2_OFC_SETTING_ADDR 0x37 -#define BMA2x2_OFC_TARGET_AXIS_OFF 1 -#define BMA2x2_OFC_TARGET_AXIS_LEN 2 -#define BMA2x2_OFC_TARGET_AXIS(_axis) \ - (BMA2x2_OFC_TARGET_AXIS_LEN * (_axis) + BMA2x2_OFC_TARGET_AXIS_OFF) -#define BMA2x2_OFC_TARGET_0G 0 -#define BMA2x2_OFC_TARGET_PLUS_1G 1 -#define BMA2x2_OFC_TARGET_MINUS_1G 2 - -#define BMA2x2_OFFSET_X_AXIS_ADDR 0x38 -#define BMA2x2_OFFSET_Y_AXIS_ADDR 0x39 -#define BMA2x2_OFFSET_Z_AXIS_ADDR 0x3A - -/* GP ADDRESS DEFINITIONS */ -#define BMA2x2_GP0_ADDR 0x3B -#define BMA2x2_GP1_ADDR 0x3C - -/* FIFO ADDRESS DEFINITIONS */ -#define BMA2x2_FIFO_MODE_ADDR 0x3E -#define BMA2x2_FIFO_DATA_OUTPUT_ADDR 0x3F -#define BMA2x2_FIFO_WML_TRIG 0x30 - -/* Sensor resolution in number of bits. This sensor has fixed resolution. */ -#define BMA2x2_RESOLUTION 12 - -/* Min and Max sampling frequency in mHz */ -#define BMA255_ACCEL_MIN_FREQ 7810 -#define BMA255_ACCEL_MAX_FREQ \ - MOTION_MAX_SENSOR_FREQUENCY(1000000, 15625) -#endif /* __CROS_EC_ACCEL_BMA2x2_H */ diff --git a/driver/accel_kionix.c b/driver/accel_kionix.c deleted file mode 100644 index ec7953551f..0000000000 --- a/driver/accel_kionix.c +++ /dev/null @@ -1,676 +0,0 @@ -/* 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. - */ - -/* - * Kionix Accelerometer driver for Chrome EC - * - * Supported: KX022, KXCJ9 - */ - -#include "accelgyro.h" -#include "common.h" -#include "console.h" -#include "driver/accel_kionix.h" -#include "driver/accel_kx022.h" -#include "driver/accel_kxcj9.h" -#include "i2c.h" -#include "math_util.h" -#include "spi.h" -#include "task.h" -#include "util.h" - -#define CPUTS(outstr) cputs(CC_ACCEL, outstr) -#define CPRINTF(format, args...) cprintf(CC_ACCEL, format, ## args) - -/* Number of times to attempt to enable sensor before giving up. */ -#define SENSOR_ENABLE_ATTEMPTS 3 - -#if defined(CONFIG_ACCEL_KXCJ9) && !defined(CONFIG_ACCEL_KX022) -#define V(s_) 1 -#elif defined(CONFIG_ACCEL_KX022) && !defined(CONFIG_ACCEL_KXCJ9) -#define V(s_) 0 -#else -#define V(s_) ((s_)->chip == MOTIONSENSE_CHIP_KXCJ9) -#endif -/* Index for which table to use. */ -#if !defined(CONFIG_ACCEL_KXCJ9) || !defined(CONFIG_ACCEL_KX022) -#define T(s_) 0 -#else -#define T(s_) V(s_) -#endif /* !defined(CONFIG_ACCEL_KXCJ9) || !defined(CONFIG_ACCEL_KX022) */ - -/* List of range values in +/-G's and their associated register values. */ -static const struct accel_param_pair ranges[][3] = { -#ifdef CONFIG_ACCEL_KX022 - { {2, KX022_GSEL_2G}, - {4, KX022_GSEL_4G}, - {8, KX022_GSEL_8G} }, -#endif /* defined(CONFIG_ACCEL_KX022) */ -#ifdef CONFIG_ACCEL_KXCJ9 - { {2, KXCJ9_GSEL_2G}, - {4, KXCJ9_GSEL_4G}, - {8, KXCJ9_GSEL_8G_14BIT} }, -#endif /* defined(CONFIG_ACCEL_KXCJ9) */ -}; - -/* List of resolution values in bits and their associated register values. */ -static const struct accel_param_pair resolutions[][2] = { -#ifdef CONFIG_ACCEL_KX022 - { {8, KX022_RES_8BIT}, - {16, KX022_RES_16BIT} }, -#endif /* defined(CONFIG_ACCEL_KX022) */ -#ifdef CONFIG_ACCEL_KXCJ9 - { {8, KXCJ9_RES_8BIT}, - {12, KXCJ9_RES_12BIT} }, -#endif /* defined(CONFIG_ACCEL_KXCJ9) */ -}; - -/* List of ODR values in mHz and their associated register values. */ -static const struct accel_param_pair datarates[][13] = { -#ifdef CONFIG_ACCEL_KX022 - /* One duplicate because table sizes must match. */ - { {781, KX022_OSA_0_781HZ}, - {781, KX022_OSA_0_781HZ}, - {1563, KX022_OSA_1_563HZ}, - {3125, KX022_OSA_3_125HZ}, - {6250, KX022_OSA_6_250HZ}, - {12500, KX022_OSA_12_50HZ}, - {25000, KX022_OSA_25_00HZ}, - {50000, KX022_OSA_50_00HZ}, - {100000, KX022_OSA_100_0HZ}, - {200000, KX022_OSA_200_0HZ}, - {400000, KX022_OSA_400_0HZ}, - {800000, KX022_OSA_800_0HZ}, - {1600000, KX022_OSA_1600HZ} }, -#endif /* defined(CONFIG_ACCEL_KX022) */ -#ifdef CONFIG_ACCEL_KXCJ9 - { {0, KXCJ9_OSA_0_000HZ}, - {781, KXCJ9_OSA_0_781HZ}, - {1563, KXCJ9_OSA_1_563HZ}, - {3125, KXCJ9_OSA_3_125HZ}, - {6250, KXCJ9_OSA_6_250HZ}, - {12500, KXCJ9_OSA_12_50HZ}, - {25000, KXCJ9_OSA_25_00HZ}, - {50000, KXCJ9_OSA_50_00HZ}, - {100000, KXCJ9_OSA_100_0HZ}, - {200000, KXCJ9_OSA_200_0HZ}, - {400000, KXCJ9_OSA_400_0HZ}, - {800000, KXCJ9_OSA_800_0HZ}, - {1600000, KXCJ9_OSA_1600_HZ} }, -#endif /* defined(CONFIG_ACCEL_KXCJ9) */ -}; - -/** - * Find index into a accel_param_pair that matches the given engineering value - * passed in. The round_up flag is used to specify whether to round up or down. - * Note, this function always returns a valid index. If the request is - * outside the range of values, it returns the closest valid index. - */ -static int find_param_index(const int eng_val, const int round_up, - const struct accel_param_pair *pairs, - const int size) -{ - int i; - - /* Linear search for index to match. */ - for (i = 0; i < size - 1; i++) { - if (eng_val <= pairs[i].val) - return i; - - if (eng_val < pairs[i+1].val) { - if (round_up) - return i + 1; - else - return i; - } - } - - return i; -} - -/** - * Read register from accelerometer. - */ -static int raw_read8(const int port, - const uint16_t i2c_spi_addr_flags, - const int reg, int *data_ptr) -{ - int rv = EC_ERROR_INVAL; - - if (SLAVE_IS_SPI(i2c_spi_addr_flags)) { -#ifdef CONFIG_SPI_ACCEL_PORT - uint8_t val; - uint8_t cmd = 0x80 | reg; - - rv = spi_transaction( - &spi_devices[SLAVE_GET_SPI_ADDR(i2c_spi_addr_flags)], - &cmd, 1, &val, 1); - if (rv == EC_SUCCESS) - *data_ptr = val; - -#endif - } else { - rv = i2c_read8(port, i2c_spi_addr_flags, - reg, data_ptr); - } - return rv; -} - -/** - * Write register from accelerometer. - */ -static int raw_write8(const int port, - const uint16_t i2c_spi_addr_flags, - const int reg, int data) -{ - int rv = EC_ERROR_INVAL; - - if (SLAVE_IS_SPI(i2c_spi_addr_flags)) { -#ifdef CONFIG_SPI_ACCEL_PORT - uint8_t cmd[2] = { reg, data }; - - rv = spi_transaction( - &spi_devices[SLAVE_GET_SPI_ADDR(i2c_spi_addr_flags)], - cmd, 2, NULL, 0); -#endif - } else { - rv = i2c_write8(port, i2c_spi_addr_flags, - reg, data); - } - return rv; -} - -static int raw_read_multi(const int port, - const uint16_t i2c_spi_addr_flags, - uint8_t reg, uint8_t *rxdata, int rxlen) -{ - int rv = EC_ERROR_INVAL; - - if (SLAVE_IS_SPI(i2c_spi_addr_flags)) { -#ifdef CONFIG_SPI_ACCEL_PORT - reg |= 0x80; - rv = spi_transaction( - &spi_devices[SLAVE_GET_SPI_ADDR(i2c_spi_addr_flags)], - ®, 1, rxdata, rxlen); -#endif - } else { - rv = i2c_read_block(port, i2c_spi_addr_flags, - reg, rxdata, rxlen); - } - return rv; -} - -/** - * Disable sensor by taking it out of operating mode. When disabled, the - * acceleration data does not change. - * - * Note: This is intended to be called in a pair with enable_sensor(). - * - * @param s Pointer to motion sensor data - * @param reg_val Pointer to location to store control register after disabling - * - * @return EC_SUCCESS if successful, EC_ERROR_* otherwise - */ -static int disable_sensor(const struct motion_sensor_t *s, int *reg_val) -{ - int i, ret, reg, pc1_field; - - reg = KIONIX_CTRL1_REG(V(s)); - pc1_field = KIONIX_PC1_FIELD(V(s)); - - /* - * Read the current state of the control register - * so that we can restore it later. - */ - for (i = 0; i < SENSOR_ENABLE_ATTEMPTS; i++) { - ret = raw_read8(s->port, s->i2c_spi_addr_flags, - reg, reg_val); - if (ret != EC_SUCCESS) - continue; - - *reg_val &= ~pc1_field; - - ret = raw_write8(s->port, s->i2c_spi_addr_flags, - reg, *reg_val); - if (ret == EC_SUCCESS) - return EC_SUCCESS; - } - return ret; -} - -/** - * Enable sensor by placing it in operating mode. - * - * Note: This is intended to be called in a pair with disable_sensor(). - * - * @param s Pointer to motion sensor data - * @param reg_val Value of the control register to write to sensor - * - * @return EC_SUCCESS if successful, EC_ERROR_* otherwise - */ -static int enable_sensor(const struct motion_sensor_t *s, int reg_val) -{ - int i, ret, reg, pc1_field; - - reg = KIONIX_CTRL1_REG(V(s)); - pc1_field = KIONIX_PC1_FIELD(V(s)); - - for (i = 0; i < SENSOR_ENABLE_ATTEMPTS; i++) { - ret = raw_read8(s->port, s->i2c_spi_addr_flags, - reg, ®_val); - if (ret != EC_SUCCESS) - continue; - -#ifdef CONFIG_KX022_ORIENTATION_SENSOR - /* Enable tilt orientation mode if lid sensor */ - if ((s->location == MOTIONSENSE_LOC_LID) && (V(s) == 0)) - reg_val |= KX022_CNTL1_TPE; -#endif - - /* Enable accelerometer based on reg_val value. */ - ret = raw_write8(s->port, s->i2c_spi_addr_flags, - reg, reg_val | pc1_field); - - /* On first success, we are done. */ - if (ret == EC_SUCCESS) - break; - } - return ret; -} - -/** - * Set a register value. - * - * @param s Pointer to motion sensor data - * @param reg Register to write to - * @param reg_val Value of the control register to write to sensor - * @param field Bitfield to modify. - * - * @return EC_SUCCESS if successful, EC_ERROR_* otherwise - */ -static int set_value(const struct motion_sensor_t *s, int reg, int val, - int field) -{ - int ret, reg_val_new, reg_val; - - /* Disable the sensor to allow for changing of critical parameters. */ - mutex_lock(s->mutex); - ret = disable_sensor(s, ®_val); - if (ret != EC_SUCCESS) { - mutex_unlock(s->mutex); - return ret; - } - - /* Determine new value of control reg and attempt to write it. */ - reg_val_new = (reg_val & ~field) | val; - ret = raw_write8(s->port, s->i2c_spi_addr_flags, - reg, reg_val_new); - - /* If successfully written, then save the range. */ - if (ret == EC_SUCCESS) - /* Re-enable the sensor. */ - ret = enable_sensor(s, reg_val_new); - - mutex_unlock(s->mutex); - return ret; -} - -static int set_range(const struct motion_sensor_t *s, int range, int rnd) -{ - int ret, index, reg, range_field, range_val; - struct kionix_accel_data *data = s->drv_data; - - /* Find index for interface pair matching the specified range. */ - index = find_param_index(range, rnd, ranges[T(s)], - ARRAY_SIZE(ranges[T(s)])); - range_field = KIONIX_RANGE_FIELD(V(s)); - reg = KIONIX_CTRL1_REG(V(s)); - range_val = ranges[T(s)][index].reg; - - ret = set_value(s, reg, range_val, range_field); - if (ret == EC_SUCCESS) - data->base.range = ranges[T(s)][index].val; - return ret; -} - -static int get_range(const struct motion_sensor_t *s) -{ - struct kionix_accel_data *data = s->drv_data; - - return data->base.range; -} - -static int set_resolution(const struct motion_sensor_t *s, int res, int rnd) -{ - int ret, index, reg, res_field, res_val; - struct kionix_accel_data *data = s->drv_data; - - /* Find index for interface pair matching the specified resolution. */ - index = find_param_index(res, rnd, resolutions[T(s)], - ARRAY_SIZE(resolutions[T(s)])); - res_val = resolutions[T(s)][index].reg; - res_field = KIONIX_RES_FIELD(V(s)); - reg = KIONIX_CTRL1_REG(V(s)); - - ret = set_value(s, reg, res_val, res_field); - if (ret == EC_SUCCESS) - data->sensor_resolution = resolutions[T(s)][index].val; - return ret; -} - -static int get_resolution(const struct motion_sensor_t *s) -{ - struct kionix_accel_data *data = s->drv_data; - - return data->sensor_resolution; -} - -static int set_data_rate(const struct motion_sensor_t *s, int rate, int rnd) -{ - int ret, index, reg, odr_field, odr_val; - struct kionix_accel_data *data = s->drv_data; - - /* Find index for interface pair matching the specified rate. */ - index = find_param_index(rate, rnd, datarates[T(s)], - ARRAY_SIZE(datarates[T(s)])); - odr_val = datarates[T(s)][index].reg; - reg = KIONIX_ODR_REG(V(s)); - odr_field = KIONIX_ODR_FIELD(V(s)); - - ret = set_value(s, reg, odr_val, odr_field); - if (ret == EC_SUCCESS) - data->base.odr = datarates[T(s)][index].val; - return ret; -} - -static int get_data_rate(const struct motion_sensor_t *s) -{ - struct kionix_accel_data *data = s->drv_data; - - return data->base.odr; -} - -static int set_offset(const struct motion_sensor_t *s, const int16_t *offset, - int16_t temp) -{ - /* temperature is ignored */ - struct kionix_accel_data *data = s->drv_data; - data->offset[X] = offset[X]; - data->offset[Y] = offset[Y]; - data->offset[Z] = offset[Z]; - return EC_SUCCESS; -} - -static int get_offset(const struct motion_sensor_t *s, int16_t *offset, - int16_t *temp) -{ - struct kionix_accel_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; -} - -#ifdef CONFIG_KX022_ORIENTATION_SENSOR -static enum motionsensor_orientation kx022_convert_orientation( - const struct motion_sensor_t *s, - int orientation) -{ - enum motionsensor_orientation res = MOTIONSENSE_ORIENTATION_UNKNOWN; - - switch (orientation) { - case KX022_ORIENT_PORTRAIT: - res = MOTIONSENSE_ORIENTATION_PORTRAIT; - break; - case KX022_ORIENT_INVERT_PORTRAIT: - res = MOTIONSENSE_ORIENTATION_UPSIDE_DOWN_PORTRAIT; - break; - case KX022_ORIENT_LANDSCAPE: - res = MOTIONSENSE_ORIENTATION_LANDSCAPE; - break; - case KX022_ORIENT_INVERT_LANDSCAPE: - res = MOTIONSENSE_ORIENTATION_UPSIDE_DOWN_LANDSCAPE; - break; - default: - break; - } - res = motion_sense_remap_orientation(s, res); - return res; -} - -static int check_orientation_locked(const struct motion_sensor_t *s) -{ - struct kionix_accel_data *data = s->drv_data; - int orientation, raw_orientation; - int ret; - - ret = raw_read8(s->port, s->i2c_spi_addr_flags, - KX022_TSCP, &raw_orientation); - if (ret != EC_SUCCESS) - return ret; - - /* mask off up and down events, we don't care about those */ - raw_orientation &= KX022_ORIENT_MASK; - if (raw_orientation && (raw_orientation != data->raw_orientation)) { - data->raw_orientation = raw_orientation; - orientation = kx022_convert_orientation(s, raw_orientation); - SET_ORIENTATION(s, orientation); - } - return ret; -} -#endif - -static int read(const struct motion_sensor_t *s, intv3_t v) -{ - uint8_t acc[6]; - uint8_t reg; - int ret, i, range, resolution; - struct kionix_accel_data *data = s->drv_data; - - /* Read 6 bytes starting at XOUT_L. */ - reg = KIONIX_XOUT_L(V(s)); - mutex_lock(s->mutex); - ret = raw_read_multi(s->port, s->i2c_spi_addr_flags, reg, acc, 6); -#ifdef CONFIG_KX022_ORIENTATION_SENSOR - if ((s->location == MOTIONSENSE_LOC_LID) && (V(s) == 0) && - (ret == EC_SUCCESS)) - ret = check_orientation_locked(s); -#endif - mutex_unlock(s->mutex); - - if (ret != EC_SUCCESS) - return ret; - - /* - * Convert acceleration to a signed 16-bit number. Note, based on - * the order of the registers: - * - * acc[0] = XOUT_L - * acc[1] = XOUT_H - * acc[2] = YOUT_L - * acc[3] = YOUT_H - * acc[4] = ZOUT_L - * acc[5] = ZOUT_H - * - * Add calibration offset before returning the data. - */ - resolution = get_resolution(s); - for (i = X; i <= Z; i++) { - if (V(s)) { - v[i] = (((int8_t)acc[i * 2 + 1]) << 4) | - (acc[i * 2] >> 4); - v[i] <<= 16 - resolution; - } else { - if (resolution == 8) - acc[i * 2] = 0; - v[i] = (((int8_t)acc[i * 2 + 1]) << 8) | acc[i * 2]; - } - } - rotate(v, *s->rot_standard_ref, v); - - /* apply offset in the device coordinates */ - range = get_range(s); - for (i = X; i <= Z; i++) - v[i] += (data->offset[i] << 5) / range; - - return EC_SUCCESS; -} - -static int init(const struct motion_sensor_t *s) -{ - int ret, val, reg, reset_field; - uint8_t timeout; - - mutex_lock(s->mutex); - if (V(s)) { - /* The chip can take up to 10ms to boot */ - reg = KIONIX_WHO_AM_I(V(s)); - timeout = 0; - do { - msleep(1); - /* Read WHO_AM_I to be sure the device has booted */ - ret = raw_read8(s->port, s->i2c_spi_addr_flags, - reg, &val); - if (ret == EC_SUCCESS) - break; - - /* Check for timeout. */ - if (timeout++ > 20) { - ret = EC_ERROR_TIMEOUT; - break; - } - } while (1); - } else { - /* Write 0x00 to the internal register for KX022 */ - reg = KX022_INTERNAL; - ret = raw_write8(s->port, s->i2c_spi_addr_flags, - reg, 0x0); - if (ret != EC_SUCCESS) { - /* - * For I2C communication, if ACK was not received - * from the first address, resend the command using - * the second address. - */ - if (!SLAVE_IS_SPI(s->i2c_spi_addr_flags)) { - const uint16_t i2c_alt_addr_flags = - I2C_GET_ADDR( - s->i2c_spi_addr_flags) - & ~2; - ret = raw_write8(s->port, - i2c_alt_addr_flags, - reg, 0x0); - } - } - } - - if (ret != EC_SUCCESS) - goto reset_failed; - - /* Issue a software reset. */ - reg = KIONIX_CTRL2_REG(V(s)); - reset_field = KIONIX_RESET_FIELD(V(s)); - - if (V(s)) { - /* Place the sensor in standby mode to make changes. */ - ret = disable_sensor(s, &val); - if (ret != EC_SUCCESS) - goto reset_failed; - ret = raw_read8(s->port, s->i2c_spi_addr_flags, reg, &val); - if (ret != EC_SUCCESS) - goto reset_failed; - - val |= reset_field; - } else { - /* Write 0 to CTRL2 for KX022 */ - ret = raw_write8(s->port, s->i2c_spi_addr_flags, reg, 0x0); - if (ret != EC_SUCCESS) - goto reset_failed; - - val = reset_field; - } - - ret = raw_write8(s->port, s->i2c_spi_addr_flags, reg, val); - if (ret != EC_SUCCESS) - goto reset_failed; - - if (V(s)) { - /* The SRST will be cleared when reset is complete. */ - timeout = 0; - do { - msleep(1); - - ret = raw_read8(s->port, s->i2c_spi_addr_flags, - reg, &val); - /* Reset complete. */ - if ((ret == EC_SUCCESS) && !(val & reset_field)) - break; - /* Check for timeout. */ - if (timeout++ > 20) { - ret = EC_ERROR_TIMEOUT; - goto reset_failed; - } - } while (1); - } else { - /* Wait 2 milliseconds for completion of the software reset. */ - msleep(2); - - reg = KX022_COTR; - ret = raw_read8(s->port, s->i2c_spi_addr_flags, reg, &val); - if (val != KX022_COTR_VAL_DEFAULT) { - CPRINTF("[%s: the software reset failed]\n", s->name); - ret = EC_ERROR_HW_INTERNAL; - goto reset_failed; - } - } - - reg = KIONIX_WHO_AM_I(V(s)); - ret = raw_read8(s->port, s->i2c_spi_addr_flags, reg, &val); - if (ret != EC_SUCCESS || val != KIONIX_WHO_AM_I_VAL(V(s))) { - ret = EC_ERROR_HW_INTERNAL; - goto reset_failed; - } - - mutex_unlock(s->mutex); - - /* Initialize with the desired parameters. */ - if (V(s)) - ret = set_resolution(s, 12, 1); - else - ret = set_resolution(s, 16, 1); - if (ret != EC_SUCCESS) - return ret; - - return sensor_init_done(s); - -reset_failed: - mutex_unlock(s->mutex); - return ret; -} - -const struct accelgyro_drv kionix_accel_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, -}; - -#ifdef CONFIG_CMD_I2C_STRESS_TEST_ACCEL -struct i2c_stress_test_dev kionix_i2c_stress_test_dev = { - .reg_info = { - .read_reg = KIONIX_WHO_AM_I(V(s)), - .read_val = KIONIX_WHO_AM_I_VAL(V(s)), - .write_reg = KIONIX_ODR_REG(V(s)), - }, - .i2c_read = &raw_read8, - .i2c_write = &raw_write8, -}; -#endif /* CONFIG_CMD_I2C_STRESS_TEST_ACCEL */ diff --git a/driver/accel_kionix.h b/driver/accel_kionix.h deleted file mode 100644 index 2491c5d39d..0000000000 --- a/driver/accel_kionix.h +++ /dev/null @@ -1,95 +0,0 @@ -/* 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. - */ - -/* Kionix Accelerometer driver for Chrome EC */ - -#ifndef __CROS_EC_ACCEL_KIONIX_H -#define __CROS_EC_ACCEL_KIONIX_H - -#include "common.h" -#include "accelgyro.h" -#include "driver/accel_kx022.h" -#include "driver/accel_kxcj9.h" - -/* - * Struct for pairing an engineering value with the register value for a - * parameter. - */ -struct accel_param_pair { - int val; /* Value in engineering units. */ - int reg; /* Corresponding register value. */ -}; - -struct kionix_accel_data { - struct accelgyro_saved_data_t base; - /* Current resolution of accelerometer. */ - int sensor_resolution; - int16_t offset[3]; -#ifdef CONFIG_KX022_ORIENTATION_SENSOR - int8_t raw_orientation; - enum motionsensor_orientation orientation; - enum motionsensor_orientation last_orientation; -#endif -}; - -extern const struct accelgyro_drv kionix_accel_drv; - -/* - * The addr field of motion_sensor support both SPI and I2C: - * - * +-------------------------------+---+ - * | 7 bit i2c address | 0 | - * +-------------------------------+---+ - * Or - * +-------------------------------+---+ - * | SPI device ID | 1 | - * +-------------------------------+---+ - */ -#define KIONIX_CTRL1_REG(v) (KX022_CNTL1 + \ - (v) * (KXCJ9_CTRL1 - KX022_CNTL1)) -#define KIONIX_CTRL2_REG(v) (KX022_CNTL2 + \ - (v) * (KXCJ9_CTRL2 - KX022_CNTL2)) -#define KIONIX_ODR_REG(v) (KX022_ODCNTL + \ - (v) * (KXCJ9_DATA_CTRL - KX022_ODCNTL)) -#define KIONIX_ODR_FIELD(v) (KX022_OSA_FIELD + \ - (v) * (KXCJ9_OSA_FIELD - KX022_OSA_FIELD)) -#define KIONIX_PC1_FIELD(v) (KX022_CNTL1_PC1 + \ - (v) * (KXCJ9_CTRL1_PC1 - KX022_CNTL1_PC1)) -#define KIONIX_RANGE_FIELD(v) (KX022_GSEL_FIELD + \ - (v) * (KXCJ9_GSEL_ALL - KX022_GSEL_FIELD)) -#define KIONIX_RES_FIELD(v) (KX022_RES_16BIT + \ - (v) * (KXCJ9_RES_12BIT - KX022_RES_16BIT)) -#define KIONIX_RESET_FIELD(v) (KX022_CNTL2_SRST + \ - (v) * (KXCJ9_CTRL2_SRST - KX022_CNTL2_SRST)) -#define KIONIX_XOUT_L(v) (KX022_XOUT_L + \ - (v) * (KXCJ9_XOUT_L - KX022_XOUT_L)) - -#define KIONIX_WHO_AM_I(v) (KX022_WHOAMI + \ - (v) * (KXCJ9_WHOAMI - KX022_WHOAMI)) - -#define KIONIX_WHO_AM_I_VAL(v) (KX022_WHO_AM_I_VAL + \ - (v) * (KXCJ9_WHO_AM_I_VAL - KX022_WHO_AM_I_VAL)) - -#ifdef CONFIG_CMD_I2C_STRESS_TEST_ACCEL -extern struct i2c_stress_test_dev kionix_i2c_stress_test_dev; -#endif - -#ifdef CONFIG_KX022_ORIENTATION_SENSOR -#define ORIENTATION_CHANGED(_sensor) \ - (((struct kionix_accel_data *)(_sensor->drv_data))->orientation != \ - ((struct kionix_accel_data *)(_sensor->drv_data))->last_orientation) - -#define GET_ORIENTATION(_sensor) \ - (((struct kionix_accel_data *)(_sensor->drv_data))->orientation) - -#define SET_ORIENTATION(_sensor, _val) \ - (((struct kionix_accel_data *)(_sensor->drv_data))->orientation = _val) - -#define SET_ORIENTATION_UPDATED(_sensor) \ - (((struct kionix_accel_data *)(_sensor->drv_data))->last_orientation = \ - ((struct kionix_accel_data *)(_sensor->drv_data))->orientation) -#endif - -#endif /* __CROS_EC_ACCEL_KIONIX_H */ diff --git a/driver/accel_kx022.h b/driver/accel_kx022.h deleted file mode 100644 index a806568c59..0000000000 --- a/driver/accel_kx022.h +++ /dev/null @@ -1,141 +0,0 @@ -/* 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. - */ - -/* KX022 gsensor module for Chrome EC */ - -#ifndef __CROS_EC_ACCEL_KX022_H -#define __CROS_EC_ACCEL_KX022_H - -/* - * 7-bit address is 001111Xb. Where 'X' is determined - * by the voltage on the ADDR pin. - */ -#define KX022_ADDR0_FLAGS 0x1e -#define KX022_ADDR1_FLAGS 0x1f -#define KX022_WHO_AM_I_VAL 0x14 - -/* Chip-specific registers */ -#define KX022_XHP_L 0x00 -#define KX022_XHP_H 0x01 -#define KX022_YHP_L 0x02 -#define KX022_YHP_H 0x03 -#define KX022_ZHP_L 0x04 -#define KX022_ZHP_H 0x05 -#define KX022_XOUT_L 0x06 -#define KX022_XOUT_H 0x07 -#define KX022_YOUT_L 0x08 -#define KX022_YOUT_H 0x09 -#define KX022_ZOUT_L 0x0a -#define KX022_ZOUT_H 0x0b -#define KX022_COTR 0x0c -#define KX022_COTR_VAL_COTC 0xAA -#define KX022_COTR_VAL_DEFAULT 0x55 -#define KX022_WHOAMI 0x0f -#define KX022_TSCP 0x10 -#define KX022_TSPP 0x11 -#define KX022_INS1 0x12 -#define KX022_INS2 0x13 -#define KX022_INS3 0x14 -#define KX022_STATUS_REG 0x15 -#define KX022_INT_REL 0x17 -#define KX022_CNTL1 0x18 -#define KX022_CNTL2 0x19 -#define KX022_CNTL3 0x1a -#define KX022_ODCNTL 0x1b -#define KX022_INC1 0x1c -#define KX022_INC2 0x1d -#define KX022_INC3 0x1e -#define KX022_INC4 0x1f -#define KX022_INC5 0x20 -#define KX022_INC6 0x21 -#define KX022_TILT_TIMER 0x22 -#define KX022_WUFC 0x23 -#define KX022_TDTRC 0x24 -#define KX022_TDTC 0x25 -#define KX022_TTH 0x26 -#define KX022_TTL 0x27 -#define KX022_FTD 0x28 -#define KX022_STD 0x29 -#define KX022_TLT 0x2a -#define KX022_TWS 0x2b -#define KX022_ATH 0x30 -#define KX022_TILT_ANGLE_LL 0x32 -#define KX022_TILT_ANGLE_HL 0x33 -#define KX022_HYST_SET 0x34 -#define KX022_LP_CNTL 0x35 -#define KX022_BUF_CNTL1 0x3a -#define KX022_BUF_CNTL2 0x3b -#define KX022_BUF_STATUS_1 0x3c -#define KX022_BUF_STATUS_2 0x3d -#define KX022_BUF_CLEAR 0x3e -#define KX022_BUF_READ 0x3f -#define KX022_SELF_TEST 0x60 -#define KX022_INTERNAL 0x7f - - -#define KX022_CNTL1_PC1 BIT(7) -#define KX022_CNTL1_WUFE BIT(1) -#define KX022_CNTL1_TPE BIT(0) - -/* TSCP orientations */ -#define KX022_ORIENT_PORTRAIT BIT(2) -#define KX022_ORIENT_INVERT_PORTRAIT BIT(3) -#define KX022_ORIENT_LANDSCAPE BIT(4) -#define KX022_ORIENT_INVERT_LANDSCAPE BIT(5) -#define KX022_ORIENT_MASK (KX022_ORIENT_PORTRAIT | \ - KX022_ORIENT_INVERT_PORTRAIT | \ - KX022_ORIENT_LANDSCAPE | \ - KX022_ORIENT_INVERT_LANDSCAPE) - -#define KX022_CNTL2_SRST BIT(7) - -#define KX022_CNTL3_OWUF_FIELD 7 - -#define KX022_INC1_IEA BIT(4) -#define KX022_INC1_IEN BIT(5) - -#define KX022_GSEL_2G (0 << 3) -#define KX022_GSEL_4G BIT(3) -#define KX022_GSEL_8G (2 << 3) -#define KX022_GSEL_FIELD (3 << 3) - -#define KX022_RES_8BIT (0 << 6) -#define KX022_RES_16BIT BIT(6) - -#define KX022_OSA_0_781HZ 8 -#define KX022_OSA_1_563HZ 9 -#define KX022_OSA_3_125HZ 0xa -#define KX022_OSA_6_250HZ 0xb -#define KX022_OSA_12_50HZ 0 -#define KX022_OSA_25_00HZ 1 -#define KX022_OSA_50_00HZ 2 -#define KX022_OSA_100_0HZ 3 -#define KX022_OSA_200_0HZ 4 -#define KX022_OSA_400_0HZ 5 -#define KX022_OSA_800_0HZ 6 -#define KX022_OSA_1600HZ 7 -#define KX022_OSA_FIELD 0xf - -#define KX022_OWUF_0_781HZ 0 -#define KX022_OWUF_1_563HZ 1 -#define KX022_OWUF_3_125HZ 2 -#define KX022_OWUF_6_250HZ 3 -#define KX022_OWUF_12_50HZ 4 -#define KX022_OWUF_25_00HZ 5 -#define KX022_OWUF_50_00HZ 6 -#define KX022_OWUF_100_0HZ 7 - -#define KX022_INC2_ZPWUE BIT(0) -#define KX022_INC2_ZNWUE BIT(1) -#define KX022_INC2_YPWUE BIT(2) -#define KX022_INC2_YNWUE BIT(3) -#define KX022_INC2_XPWUE BIT(4) -#define KX022_INC2_XNWUE BIT(5) - -/* Min and Max sampling frequency in mHz */ -#define KX022_ACCEL_MIN_FREQ 12500 -#define KX022_ACCEL_MAX_FREQ MOTION_MAX_SENSOR_FREQUENCY(1600000, 6250) - -#endif /* __CROS_EC_ACCEL_KX022_H */ diff --git a/driver/accel_kxcj9.h b/driver/accel_kxcj9.h deleted file mode 100644 index f7488317f0..0000000000 --- a/driver/accel_kxcj9.h +++ /dev/null @@ -1,111 +0,0 @@ -/* Copyright 2014 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. - */ - -/* KXCJ9 gsensor module for Chrome EC */ - -#ifndef __CROS_EC_ACCEL_KXCJ9_H -#define __CROS_EC_ACCEL_KXCJ9_H - -#include "task.h" - -/* - * 7-bit address is 000111Xb. Where 'X' is determined - * by the voltage on the ADDR pin. - */ -#define KXCJ9_ADDR0_FLAGS 0x0E -#define KXCJ9_ADDR1_FLAGS 0x0D -#define KXCJ9_WHO_AM_I_VAL 0x0A - -/* Chip-specific registers */ -#define KXCJ9_XOUT_L 0x06 -#define KXCJ9_XOUT_H 0x07 -#define KXCJ9_YOUT_L 0x08 -#define KXCJ9_YOUT_H 0x09 -#define KXCJ9_ZOUT_L 0x0a -#define KXCJ9_ZOUT_H 0x0b -#define KXCJ9_DCST_RESP 0x0c -#define KXCJ9_WHOAMI 0x0f -#define KXCJ9_INT_SRC1 0x16 -#define KXCJ9_INT_SRC2 0x17 -#define KXCJ9_STATUS 0x18 -#define KXCJ9_INT_REL 0x1a -#define KXCJ9_CTRL1 0x1b -#define KXCJ9_CTRL2 0x1d -#define KXCJ9_INT_CTRL1 0x1e -#define KXCJ9_INT_CTRL2 0x1f -#define KXCJ9_DATA_CTRL 0x21 -#define KXCJ9_WAKEUP_TIMER 0x29 -#define KXCJ9_SELF_TEST 0x3a -#define KXCJ9_WAKEUP_THRESHOLD 0x6a - -#define KXCJ9_INT_SRC1_WUFS BIT(1) -#define KXCJ9_INT_SRC1_DRDY BIT(4) - -#define KXCJ9_INT_SRC2_ZPWU BIT(0) -#define KXCJ9_INT_SRC2_ZNWU BIT(1) -#define KXCJ9_INT_SRC2_YPWU BIT(2) -#define KXCJ9_INT_SRC2_YNWU BIT(3) -#define KXCJ9_INT_SRC2_XPWU BIT(4) -#define KXCJ9_INT_SRC2_XNWU BIT(5) - -#define KXCJ9_STATUS_INT BIT(4) - -#define KXCJ9_CTRL1_WUFE BIT(1) -#define KXCJ9_CTRL1_DRDYE BIT(5) -#define KXCJ9_CTRL1_PC1 BIT(7) - -#define KXCJ9_GSEL_2G (0 << 3) -#define KXCJ9_GSEL_4G BIT(3) -#define KXCJ9_GSEL_8G (2 << 3) -#define KXCJ9_GSEL_8G_14BIT (3 << 3) -#define KXCJ9_GSEL_ALL (3 << 3) - -#define KXCJ9_RES_8BIT (0 << 6) -#define KXCJ9_RES_12BIT BIT(6) - -#define KXCJ9_CTRL2_OWUF (7 << 0) -#define KXCJ9_CTRL2_DCST BIT(4) -#define KXCJ9_CTRL2_SRST BIT(7) - -#define KXCJ9_OWUF_0_781HZ 0 -#define KXCJ9_OWUF_1_563HZ 1 -#define KXCJ9_OWUF_3_125HZ 2 -#define KXCJ9_OWUF_6_250HZ 3 -#define KXCJ9_OWUF_12_50HZ 4 -#define KXCJ9_OWUF_25_00HZ 5 -#define KXCJ9_OWUF_50_00HZ 6 -#define KXCJ9_OWUF_100_0HZ 7 - -#define KXCJ9_INT_CTRL1_IEL BIT(3) -#define KXCJ9_INT_CTRL1_IEA BIT(4) -#define KXCJ9_INT_CTRL1_IEN BIT(5) - -#define KXCJ9_INT_CTRL2_ZPWUE BIT(0) -#define KXCJ9_INT_CTRL2_ZNWUE BIT(1) -#define KXCJ9_INT_CTRL2_YPWUE BIT(2) -#define KXCJ9_INT_CTRL2_YNWUE BIT(3) -#define KXCJ9_INT_CTRL2_XPWUE BIT(4) -#define KXCJ9_INT_CTRL2_XNWUE BIT(5) - -#define KXCJ9_OSA_0_000HZ 0 -#define KXCJ9_OSA_0_781HZ 8 -#define KXCJ9_OSA_1_563HZ 9 -#define KXCJ9_OSA_3_125HZ 0xa -#define KXCJ9_OSA_6_250HZ 0xb -#define KXCJ9_OSA_12_50HZ 0 -#define KXCJ9_OSA_25_00HZ 1 -#define KXCJ9_OSA_50_00HZ 2 -#define KXCJ9_OSA_100_0HZ 3 -#define KXCJ9_OSA_200_0HZ 4 -#define KXCJ9_OSA_400_0HZ 5 -#define KXCJ9_OSA_800_0HZ 6 -#define KXCJ9_OSA_1600_HZ 7 -#define KXCJ9_OSA_FIELD 0xf - -/* Min and Max sampling frequency in mHz */ -#define KXCJ9_ACCEL_MIN_FREQ 12500 -#define KXCJ9_ACCEL_MAX_FREQ MOTION_MAX_SENSOR_FREQUENCY(1600000, 6250) - -#endif /* __CROS_EC_ACCEL_KXCJ9_H */ diff --git a/driver/accel_lis2dh.c b/driver/accel_lis2dh.c deleted file mode 100644 index d7307d46e3..0000000000 --- a/driver/accel_lis2dh.c +++ /dev/null @@ -1,261 +0,0 @@ -/* 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. - */ - -/** - * Accelerometer module driver for Chrome EC 3D digital accelerometers: - * LIS2DH/LIS2DH12/LNG2DM - */ - -#include "accelgyro.h" -#include "common.h" -#include "console.h" -#include "hooks.h" -#include "hwtimer.h" -#include "i2c.h" -#include "math_util.h" -#include "task.h" -#include "util.h" -#include "driver/accel_lis2dh.h" -#include "driver/stm_mems_common.h" - -#define CPUTS(outstr) cputs(CC_ACCEL, outstr) -#define CPRINTS(format, args...) cprints(CC_ACCEL, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_ACCEL, format, ## args) - -/** - * set_range - set full scale range - * @s: Motion sensor pointer - * @range: Range - * @rnd: Round up/down flag - */ -static int set_range(const struct motion_sensor_t *s, int range, int rnd) -{ - int err, normalized_range; - struct stprivate_data *data = s->drv_data; - int val; - - val = LIS2DH_FS_TO_REG(range); - normalized_range = ST_NORMALIZE_RATE(range); - - if (rnd && (range < normalized_range)) - val++; - - /* Adjust rounded values */ - if (val > LIS2DH_FS_16G_VAL) { - val = LIS2DH_FS_16G_VAL; - normalized_range = 16; - } - - if (val < LIS2DH_FS_2G_VAL) { - val = LIS2DH_FS_2G_VAL; - normalized_range = 2; - } - - /* - * Lock accel resource to prevent another task from attempting - * to write accel parameters until we are done. - */ - mutex_lock(s->mutex); - err = st_write_data_with_mask(s, LIS2DH_CTRL4_ADDR, LIS2DH_FS_MASK, - val); - - /* Save Gain in range for speed up data path */ - if (err == EC_SUCCESS) - data->base.range = normalized_range; - - mutex_unlock(s->mutex); - return EC_SUCCESS; -} - -static int get_range(const struct motion_sensor_t *s) -{ - struct stprivate_data *data = s->drv_data; - - return data->base.range; -} - -static int set_data_rate(const struct motion_sensor_t *s, int rate, int rnd) -{ - int ret, normalized_rate; - struct stprivate_data *data = s->drv_data; - uint8_t reg_val; - - mutex_lock(s->mutex); - - if (rate == 0) { - /* Power Off device */ - ret = st_write_data_with_mask( - s, LIS2DH_CTRL1_ADDR, - LIS2DH_ACC_ODR_MASK, LIS2DH_ODR_0HZ_VAL); - goto unlock_rate; - } - - reg_val = LIS2DH_ODR_TO_REG(rate); - normalized_rate = LIS2DH_ODR_TO_NORMALIZE(rate); - - if (rnd && (normalized_rate < rate)) { - reg_val++; - normalized_rate = LIS2DH_REG_TO_NORMALIZE(reg_val); - } - - if (normalized_rate > LIS2DH_ODR_MAX_VAL || - normalized_rate < LIS2DH_ODR_MIN_VAL) - return EC_RES_INVALID_PARAM; - - /* - * Lock accel resource to prevent another task from attempting - * to write accel parameters until we are done - */ - ret = st_write_data_with_mask(s, LIS2DH_CTRL1_ADDR, LIS2DH_ACC_ODR_MASK, - reg_val); - if (ret == EC_SUCCESS) - data->base.odr = normalized_rate; - -unlock_rate: - mutex_unlock(s->mutex); - return ret; -} - -static int is_data_ready(const struct motion_sensor_t *s, int *ready) -{ - int ret, tmp; - - ret = st_raw_read8(s->port, s->i2c_spi_addr_flags, - LIS2DH_STATUS_REG, &tmp); - if (ret != EC_SUCCESS) { - CPRINTS("%s type:0x%X RS Error", s->name, s->type); - return ret; - } - - *ready = (LIS2DH_STS_XLDA_UP == (tmp & LIS2DH_STS_XLDA_UP)); - - return EC_SUCCESS; -} - -static int read(const struct motion_sensor_t *s, intv3_t v) -{ - uint8_t raw[OUT_XYZ_SIZE]; - int ret, tmp = 0; - - ret = is_data_ready(s, &tmp); - if (ret != EC_SUCCESS) - return ret; - - /* - * If sensor data is not ready, return the previous read data. - * Note: return success so that motion senor task can read again - * to get the latest updated sensor data quickly. - */ - if (!tmp) { - if (v != s->raw_xyz) - memcpy(v, s->raw_xyz, sizeof(s->raw_xyz)); - return EC_SUCCESS; - } - - /* Read output data bytes starting at LIS2DH_OUT_X_L_ADDR */ - ret = st_raw_read_n(s->port, s->i2c_spi_addr_flags, - LIS2DH_OUT_X_L_ADDR, raw, OUT_XYZ_SIZE); - if (ret != EC_SUCCESS) { - CPRINTS("%s type:0x%X RD XYZ Error", s->name, s->type); - return ret; - } - - /* Transform from LSB to real data with rotation and gain */ - st_normalize(s, v, raw); - - return EC_SUCCESS; -} - -static int init(const struct motion_sensor_t *s) -{ - int ret = 0, tmp; - struct stprivate_data *data = s->drv_data; - int count = 10; - - /* - * lis2de need 5 milliseconds to complete boot procedure after - * device power-up. When sensor is powered on, it can't be - * accessed immediately. We need wait serval loops to let sensor - * complete boot procedure. - */ - do { - ret = st_raw_read8(s->port, s->i2c_spi_addr_flags, - LIS2DH_WHO_AM_I_REG, &tmp); - if (ret != EC_SUCCESS) { - udelay(10); - count--; - } else { - break; - } - } while (count > 0); - - if (ret != EC_SUCCESS) - return ret; - - if (tmp != LIS2DH_WHO_AM_I) - return EC_ERROR_ACCESS_DENIED; - - mutex_lock(s->mutex); - /* - * Device can be re-initialized after a reboot so any control - * register must be restored to it's default. - */ - /* Enable all accel axes data and clear old settings */ - ret = st_raw_write8(s->port, s->i2c_spi_addr_flags, - LIS2DH_CTRL1_ADDR, LIS2DH_ENABLE_ALL_AXES); - if (ret != EC_SUCCESS) - goto err_unlock; - - ret = st_raw_write8(s->port, s->i2c_spi_addr_flags, - LIS2DH_CTRL2_ADDR, LIS2DH_CTRL2_RESET_VAL); - if (ret != EC_SUCCESS) - goto err_unlock; - - ret = st_raw_write8(s->port, s->i2c_spi_addr_flags, - LIS2DH_CTRL3_ADDR, LIS2DH_CTRL3_RESET_VAL); - if (ret != EC_SUCCESS) - goto err_unlock; - - /* Enable BDU */ - ret = st_raw_write8(s->port, s->i2c_spi_addr_flags, - LIS2DH_CTRL4_ADDR, LIS2DH_BDU_MASK); - if (ret != EC_SUCCESS) - goto err_unlock; - - ret = st_raw_write8(s->port, s->i2c_spi_addr_flags, - LIS2DH_CTRL5_ADDR, LIS2DH_CTRL5_RESET_VAL); - if (ret != EC_SUCCESS) - goto err_unlock; - - ret = st_raw_write8(s->port, s->i2c_spi_addr_flags, - LIS2DH_CTRL6_ADDR, LIS2DH_CTRL6_RESET_VAL); - if (ret != EC_SUCCESS) - goto err_unlock; - - mutex_unlock(s->mutex); - - /* Set default resolution */ - data->resol = LIS2DH_RESOLUTION; - - return sensor_init_done(s); - -err_unlock: - mutex_unlock(s->mutex); - CPRINTS("%s: MS Init type:0x%X Error", s->name, s->type); - - return ret; -} - -const struct accelgyro_drv lis2dh_drv = { - .init = init, - .read = read, - .set_range = set_range, - .get_range = get_range, - .get_resolution = st_get_resolution, - .set_data_rate = set_data_rate, - .get_data_rate = st_get_data_rate, - .set_offset = st_set_offset, - .get_offset = st_get_offset, -}; diff --git a/driver/accel_lis2dh.h b/driver/accel_lis2dh.h deleted file mode 100644 index 2a3108aab8..0000000000 --- a/driver/accel_lis2dh.h +++ /dev/null @@ -1,133 +0,0 @@ -/* 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. - */ - -/* LIS2DH/LIS2DE/LNG2DM accelerometer module for Chrome EC */ - -#ifndef __CROS_EC_ACCEL_LIS2DH_H -#define __CROS_EC_ACCEL_LIS2DH_H - -#include "driver/stm_mems_common.h" - -/* - * LIS2DH/LIS2DE: - * - * 7-bit address is 0011 00X b. Where 'X' is determined - * by the voltage on the ADDR pin - */ -#define LIS2DH_ADDR0_FLAGS 0x18 -#define LIS2DH_ADDR1_FLAGS 0x19 - -/* - * LNG2DM: - * - * 8-bit address is 0101 00XW b. Where 'X' is determined - * by the voltage on the ADDR pin, and 'W' is read write bit - */ -#define LNG2DM_ADDR0_FLAGS 0x28 -#define LNG2DM_ADDR1_FLAGS 0x29 - -/* Who Am I */ -#define LIS2DH_WHO_AM_I_REG 0x0f -#define LIS2DH_WHO_AM_I 0x33 - -/* COMMON DEFINE FOR ACCEL SENSOR */ -#define LIS2DH_EN_BIT 0x01 -#define LIS2DH_DIS_BIT 0x00 - -#define LIS2DH_INT2_ON_INT1_ADDR 0x13 -#define LIS2DH_INT2_ON_INT1_MASK 0x20 - -#define LIS2DH_OUT_X_L_ADDR 0x28 - -#define LIS2DH_CTRL1_ADDR 0x20 -#define LIS2DH_INT2_ON_INT1_MASK 0x20 -#define LIS2DH_ENABLE_ALL_AXES 0x07 - -#define LIS2DH_CTRL2_ADDR 0x21 -#define LIS2DH_CTRL2_RESET_VAL 0x00 - -#define LIS2DH_CTRL3_ADDR 0x22 -#define LIS2DH_CTRL3_RESET_VAL 0x00 - -#define LIS2DH_CTRL4_ADDR 0x23 -#define LIS2DH_BDU_MASK 0x80 - -#define LIS2DH_CTRL5_ADDR 0x24 -#define LIS2DH_CTRL5_RESET_VAL 0x00 - -#define LIS2DH_CTRL6_ADDR 0x25 -#define LIS2DH_CTRL6_RESET_VAL 0x00 - -#define LIS2DH_STATUS_REG 0x27 -#define LIS2DH_STS_XLDA_UP 0x80 - -#define LIS2DH_FS_2G_VAL 0x00 -#define LIS2DH_FS_4G_VAL 0x01 -#define LIS2DH_FS_8G_VAL 0x02 -#define LIS2DH_FS_16G_VAL 0x03 - -/* Interrupt source status register */ -#define LIS2DH_INT1_SRC_REG 0x31 - -/* Output data rate Mask register */ -#define LIS2DH_ACC_ODR_MASK 0xf0 - -/* Acc data rate */ -enum lis2dh_odr { - LIS2DH_ODR_0HZ_VAL = 0, - LIS2DH_ODR_1HZ_VAL, - LIS2DH_ODR_10HZ_VAL, - LIS2DH_ODR_25HZ_VAL, - LIS2DH_ODR_50HZ_VAL, - LIS2DH_ODR_100HZ_VAL, - LIS2DH_ODR_200HZ_VAL, - LIS2DH_ODR_400HZ_VAL, - LIS2DH_ODR_LIST_NUM -}; - -/* Absolute maximum rate for sensor */ -#define LIS2DH_ODR_MIN_VAL 1000 -#define LIS2DH_ODR_MAX_VAL \ - MOTION_MAX_SENSOR_FREQUENCY(400000, 25000) - -/* Return ODR reg value based on data rate set */ -#define LIS2DH_ODR_TO_REG(_odr) \ - (_odr <= 1000) ? LIS2DH_ODR_1HZ_VAL : \ - (_odr <= 10000) ? LIS2DH_ODR_10HZ_VAL : \ - ((31 - __builtin_clz(_odr / 25000))) + 3 - -/* Return ODR real value normalized to sensor capabilities */ -#define LIS2DH_ODR_TO_NORMALIZE(_odr) \ - (_odr <= 1000) ? 1000 : (_odr <= 10000) ? 10000 : \ - (25000 * (1 << (31 - __builtin_clz(_odr / 25000)))) - -/* Return ODR real value normalized to sensor capabilities from reg value */ -#define LIS2DH_REG_TO_NORMALIZE(_reg) \ - (_reg == LIS2DH_ODR_1HZ_VAL) ? 1000 : \ - (_reg == LIS2DH_ODR_10HZ_VAL) ? 10000 : (25000 * (1 << (_reg - 3))) - -/* Full scale range Mask register */ -#define LIS2DH_FS_MASK 0x30 - -/* FS reg value from Full Scale */ -#define LIS2DH_FS_TO_REG(_fs) (__fls(_fs) - 1) - -/* - * Sensor resolution in number of bits - * - * lis2dh has variable precision (8/10/12 bits) depending Power Mode - * selected, here Only Normal Power mode supported (10 bits). - * - * lis2de/lng2dm only support 8bit resolution. - */ -#if defined(CONFIG_ACCEL_LIS2DE) || defined(CONFIG_ACCEL_LNG2DM) -#define LIS2DH_RESOLUTION 8 -#elif defined(CONFIG_ACCEL_LIS2DH) -#define LIS2DH_RESOLUTION 10 -#endif - -extern const struct accelgyro_drv lis2dh_drv; - -#endif /* __CROS_EC_ACCEL_LIS2DH_H */ diff --git a/driver/accel_lis2dw12.c b/driver/accel_lis2dw12.c deleted file mode 100644 index ba7514309f..0000000000 --- a/driver/accel_lis2dw12.c +++ /dev/null @@ -1,602 +0,0 @@ -/* Copyright 2019 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. - */ - -/* - * LIS2DW12 accelerometer module for Chrome EC 3D digital accelerometer. - * For more details on LIS2DW12 device please refers to www.st.com. - */ -#include "accelgyro.h" -#include "common.h" -#include "console.h" -#include "driver/accel_lis2dw12.h" -#include "hooks.h" -#include "hwtimer.h" -#include "math_util.h" -#include "task.h" -#include "util.h" - -#define CPRINTF(format, args...) cprintf(CC_ACCEL, format, ## args) -#define CPRINTS(format, args...) cprints(CC_ACCEL, format, ## args) - -/* Only when configured as base accel sensor, fifo and interrupt - * are supported. - */ -#ifdef CONFIG_ACCEL_LIS2DW_AS_BASE - -#ifdef CONFIG_ACCEL_FIFO -static volatile uint32_t last_interrupt_timestamp; - -/** - * lis2dw12_enable_fifo - Enable/Disable FIFO in LIS2DW12 - * @s: Motion sensor pointer - * @mode: fifo_modes - */ -static int lis2dw12_enable_fifo(const struct motion_sensor_t *s, - enum lis2dw12_fmode mode) -{ - return st_write_data_with_mask(s, LIS2DW12_FIFO_CTRL_ADDR, - LIS2DW12_FIFO_MODE_MASK, mode); -} - -/** - * Load data from internal sensor FIFO. - * @s: Motion sensor pointer - */ -static int lis2dw12_load_fifo(struct motion_sensor_t *s, int nsamples, - uint32_t *last_fifo_read_ts) -{ - int ret, left, length, i; - struct ec_response_motion_sensor_data vect; - uint32_t interrupt_timestamp = last_interrupt_timestamp; - int *axis = s->raw_xyz; - uint8_t fifo[FIFO_READ_LEN]; - - /* Each sample are OUT_XYZ_SIZE bytes. */ - left = nsamples * OUT_XYZ_SIZE; - - do { - /* - * Limit FIFO read data to burst of FIFO_READ_LEN size because - * read operatios in under i2c mutex lock. - */ - if (left > FIFO_READ_LEN) - length = FIFO_READ_LEN; - else - length = left; - - ret = st_raw_read_n(s->port, s->i2c_spi_addr_flags, - LIS2DW12_OUT_X_L_ADDR, fifo, length); - *last_fifo_read_ts = __hw_clock_source_read(); - if (ret != EC_SUCCESS) - return ret; - - for (i = 0; i < length; i += OUT_XYZ_SIZE) { - /* Apply precision, sensitivity and rotation vector. */ - st_normalize(s, axis, &fifo[i]); - - /* Fill vector array. */ - vect.data[X] = axis[X]; - vect.data[Y] = axis[Y]; - vect.data[Z] = axis[Z]; - vect.flags = 0; - vect.sensor_num = 0; - motion_sense_fifo_stage_data(&vect, s, 3, - interrupt_timestamp); - } - left -= length; - } while (left > 0); - - motion_sense_fifo_commit_data(); - - return EC_SUCCESS; -} - -/** - * lis2dw12_get_fifo_samples - check for stored FIFO samples. - */ -static int lis2dw12_get_fifo_samples(struct motion_sensor_t *s, int *nsamples) -{ - int ret, tmp; - - ret = st_raw_read8(s->port, s->i2c_spi_addr_flags, - LIS2DW12_FIFO_SAMPLES_ADDR, &tmp); - if (ret != EC_SUCCESS) - return ret; - - *nsamples = tmp & LIS2DW12_FIFO_DIFF_MASK; - - return EC_SUCCESS; -} - -static int fifo_data_avail(struct motion_sensor_t *s) -{ - int ret, nsamples; - - if (s->flags & MOTIONSENSE_FLAG_INT_SIGNAL) - return gpio_get_level(s->int_signal) == - !!(MOTIONSENSE_FLAG_INT_ACTIVE_HIGH & s->flags); - - ret = lis2dw12_get_fifo_samples(s, &nsamples); - /* If we failed to read the FIFO size assume empty. */ - if (ret != EC_SUCCESS) - return 0; - return nsamples; -} -#endif /* CONFIG_ACCEL_FIFO */ - -/** - * lis2dw12_config_interrupt- Configure interrupt for supported features. - * @s: Motion sensor pointer - * - * Must works with interface mutex locked - */ -static int lis2dw12_config_interrupt(const struct motion_sensor_t *s) -{ - int ret = EC_SUCCESS; - -#ifdef CONFIG_ACCEL_FIFO_THRES - /* Configure FIFO watermark level. */ - ret = st_write_data_with_mask(s, LIS2DW12_FIFO_CTRL_ADDR, - LIS2DW12_FIFO_THRESHOLD_MASK, 1); - if (ret != EC_SUCCESS) - return ret; - - /* Enable interrupt on FIFO watermask and route to int1. */ - ret = st_write_data_with_mask(s, LIS2DW12_INT1_FTH_ADDR, - LIS2DW12_INT1_FTH_MASK, LIS2DW12_EN_BIT); - if (ret != EC_SUCCESS) - return ret; -#endif /* CONFIG_ACCEL_FIFO */ - -#ifdef CONFIG_GESTURE_SENSOR_DOUBLE_TAP - /* - * Configure D-TAP event detection on 3 axis. - * For more details please refer to AN5038. - */ - ret = st_raw_write8(s->port, s->i2c_spi_addr_flags, - LIS2DW12_TAP_THS_X_ADDR, 0x09); - if (ret != EC_SUCCESS) - return ret; - ret = st_raw_write8(s->port, s->i2c_spi_addr_flags, - LIS2DW12_TAP_THS_Y_ADDR, 0x09); - if (ret != EC_SUCCESS) - return ret; - ret = st_raw_write8(s->port, s->i2c_spi_addr_flags, - LIS2DW12_TAP_THS_Z_ADDR, 0xE9); - if (ret != EC_SUCCESS) - return ret; - ret = st_raw_write8(s->port, s->i2c_spi_addr_flags, - LIS2DW12_INT_DUR_ADDR, 0x7F); - if (ret != EC_SUCCESS) - return ret; - - /* Enable D-TAP event detection. */ - ret = st_write_data_with_mask(s, LIS2DW12_WAKE_UP_THS_ADDR, - LIS2DW12_SINGLE_DOUBLE_TAP, - LIS2DW12_EN_BIT); - if (ret != EC_SUCCESS) - return ret; - - /* - * Enable D-TAP detection on int_1 pad. In any case D-TAP event - * can be detected only if ODR is over 200 Hz. - */ - ret = st_write_data_with_mask(s, LIS2DW12_INT1_TAP_ADDR, - LIS2DW12_INT1_DTAP_MASK, - LIS2DW12_EN_BIT); -#endif /* CONFIG_GESTURE_SENSOR_DOUBLE_TAP */ - return ret; -} - -static void lis2dw12_handle_interrupt_for_fifo(uint32_t ts) -{ -#ifdef CONFIG_ACCEL_FIFO - if (time_after(ts, last_interrupt_timestamp)) - last_interrupt_timestamp = ts; -#endif - task_set_event(TASK_ID_MOTIONSENSE, - CONFIG_ACCEL_LIS2DW12_INT_EVENT, 0); -} - -/** - * lis2dw12_interrupt - interrupt from int pin of sensor - * Schedule Motion Sense Task to manage Interrupts. - */ -void lis2dw12_interrupt(enum gpio_signal signal) -{ - lis2dw12_handle_interrupt_for_fifo(__hw_clock_source_read()); -} - -/** - * lis2dw12_irq_handler - bottom half of the interrupt stack. - */ -static int lis2dw12_irq_handler(struct motion_sensor_t *s, uint32_t *event) -{ - int ret = EC_SUCCESS; - - if ((s->type != MOTIONSENSE_TYPE_ACCEL) || - (!(*event & CONFIG_ACCEL_LIS2DW12_INT_EVENT))) { - return EC_ERROR_NOT_HANDLED; - } - -#ifdef CONFIG_GESTURE_SENSOR_DOUBLE_TAP - { - int status = 0; - - /* Read Status register to check TAP events. */ - st_raw_read8(s->port, s->i2c_spi_addr_flags, - LIS2DW12_STATUS_TAP, &status); - if (status & LIS2DW12_DOUBLE_TAP) - *event |= CONFIG_GESTURE_TAP_EVENT; - } -#endif /* CONFIG_GESTURE_SENSOR_DOUBLE_TAP */ - -#ifdef CONFIG_ACCEL_FIFO - { - int nsamples; - uint32_t last_fifo_read_ts; - uint32_t triggering_interrupt_timestamp = - last_interrupt_timestamp; - - ret = lis2dw12_get_fifo_samples(s, &nsamples); - if (ret != EC_SUCCESS) - return ret; - - last_fifo_read_ts = __hw_clock_source_read(); - if (nsamples == 0) - return EC_SUCCESS; - - ret = lis2dw12_load_fifo(s, nsamples, &last_fifo_read_ts); - - /* - * Check if FIFO isn't empty and we never got an interrupt. - * This can happen if new entries were added to the FIFO after - * the count was read, but before the FIFO was cleared out. - * In the long term it might be better to use the last - * spread timestamp instead. - */ - if (fifo_data_avail(s) && - triggering_interrupt_timestamp == last_interrupt_timestamp) - lis2dw12_handle_interrupt_for_fifo(last_fifo_read_ts); - } -#endif /* CONFIG_ACCEL_FIFO */ - - return ret; -} - -#endif /* CONFIG_ACCEL_LIS2DW_AS_BASE */ - -/** - * set_power_mode - set sensor power mode - * @s: Motion sensor pointer - * @mode: LIS2DW12_LOW_POWER, LIS2DW12_HIGH_PERF - * @lpmode: LIS2DW12_LOW_POWER_MODE_2, - * LIS2DW12_LOW_POWER_MODE_3, - * LIS2DW12_LOW_POWER_MODE_4 - * - * TODO: LIS2DW12_LOW_POWER_MODE_1 not implemented because output differ - * in resolution - */ -static int set_power_mode(const struct motion_sensor_t *s, - enum lis2sw12_mode mode, - enum lis2sw12_lpmode lpmode) -{ - int ret = EC_SUCCESS; - - if (mode == LIS2DW12_LOW_POWER && - lpmode == LIS2DW12_LOW_POWER_MODE_1) - return EC_ERROR_UNIMPLEMENTED; - - /* Set Mode and Low Power Mode. */ - ret = st_write_data_with_mask(s, LIS2DW12_ACC_MODE_ADDR, - LIS2DW12_ACC_MODE_MASK, mode); - if (ret != EC_SUCCESS) - return ret; - - ret = st_write_data_with_mask(s, LIS2DW12_ACC_LPMODE_ADDR, - LIS2DW12_ACC_LPMODE_MASK, lpmode); - return ret; -} - -/** - * set_range - set full scale range - * @s: Motion sensor pointer - * @range: Range - * @rnd: Round up/down flag - */ -static int set_range(const struct motion_sensor_t *s, int range, int rnd) -{ - int err = EC_SUCCESS; - uint8_t reg_val; - struct stprivate_data *data = s->drv_data; - int newrange = range; - - /* Adjust and check rounded value. */ - if (rnd && (newrange < LIS2DW12_NORMALIZE_FS(newrange))) - newrange <<= 1; - - if (newrange > LIS2DW12_ACCEL_FS_MAX_VAL) - newrange = LIS2DW12_ACCEL_FS_MAX_VAL; - - reg_val = LIS2DW12_FS_REG(newrange); - - mutex_lock(s->mutex); -#if defined(CONFIG_ACCEL_FIFO) && defined(CONFIG_ACCEL_LIS2DW_AS_BASE) - /* - * FIFO stop collecting events. Restart FIFO in Bypass mode. - * If Range is changed all samples in FIFO must be discharged because - * with a different sensitivity. - */ - err = lis2dw12_enable_fifo(s, LIS2DW12_FIFO_BYPASS_MODE); - if (err != EC_SUCCESS) - goto unlock_rate; -#endif /* CONFIG_ACCEL_FIFO && CONFIG_ACCEL_LIS2DW_AS_BASE */ - - err = st_write_data_with_mask(s, LIS2DW12_FS_ADDR, LIS2DW12_FS_MASK, - reg_val); - if (err == EC_SUCCESS) - data->base.range = newrange; -#if defined(CONFIG_ACCEL_FIFO) && defined(CONFIG_ACCEL_LIS2DW_AS_BASE) - /* FIFO restart collecting events in Cont. mode. */ - err = lis2dw12_enable_fifo(s, LIS2DW12_FIFO_CONT_MODE); - -unlock_rate: -#endif /* CONFIG_ACCEL_FIFO && CONFIG_ACCEL_LIS2DW_AS_BASE */ - mutex_unlock(s->mutex); - - return err; -} - -static int get_range(const struct motion_sensor_t *s) -{ - struct stprivate_data *data = s->drv_data; - - return data->base.range; -} - -/** - * ODR reg value from selected data rate in mHz. - */ -static uint8_t odr_to_reg(int odr) -{ - if (odr <= LIS2DW12_ODR_MIN_VAL) - return LIS2DW12_ODR_12HZ_VAL; - - return (__fls(odr / LIS2DW12_ODR_MIN_VAL) + LIS2DW12_ODR_12HZ_VAL); -} - -/** - * Normalized ODR value from selected data rate in mHz. - */ -static int odr_to_normalize(int odr) -{ - if (odr <= LIS2DW12_ODR_MIN_VAL) - return LIS2DW12_ODR_MIN_VAL; - - return (LIS2DW12_ODR_MIN_VAL << (__fls(odr / LIS2DW12_ODR_MIN_VAL))); -} - -static int set_data_rate(const struct motion_sensor_t *s, int rate, int rnd) -{ - int ret, normalized_rate; - struct stprivate_data *data = s->drv_data; - uint8_t reg_val; - - mutex_lock(s->mutex); - -#if defined(CONFIG_ACCEL_FIFO) && defined(CONFIG_ACCEL_LIS2DW_AS_BASE) - /* FIFO stop collecting events. Restart FIFO in Bypass mode. */ - ret = lis2dw12_enable_fifo(s, LIS2DW12_FIFO_BYPASS_MODE); - if (ret != EC_SUCCESS) - goto unlock_rate; -#endif /* CONFIG_ACCEL_FIFO && CONFIG_ACCEL_LIS2DW_AS_BASE */ - - if (rate == 0) { - ret = st_write_data_with_mask(s, LIS2DW12_ACC_ODR_ADDR, - LIS2DW12_ACC_ODR_MASK, - LIS2DW12_ODR_POWER_OFF_VAL); - if (ret == EC_SUCCESS) - data->base.odr = LIS2DW12_ODR_POWER_OFF_VAL; - - goto unlock_rate; - } - - reg_val = odr_to_reg(rate); - normalized_rate = odr_to_normalize(rate); - - if (rnd && (normalized_rate < rate)) { - reg_val++; - normalized_rate <<= 1; - } - - if (reg_val > LIS2DW12_ODR_1_6kHZ_VAL) { - reg_val = LIS2DW12_ODR_1_6kHZ_VAL; - normalized_rate = LIS2DW12_ODR_MAX_VAL; - } else if (reg_val < LIS2DW12_ODR_12HZ_VAL) { - reg_val = LIS2DW12_ODR_12HZ_VAL; - normalized_rate = LIS2DW12_ODR_MIN_VAL; - } - - /* lis2dwl supports 14 bit resolution only at high performance mode, - * and it will always stay at high performance mode from initialization. - * But lis2dw12 needs switch low power mode according to odr value. - */ -#ifndef CONFIG_ACCEL_LIS2DWL - if (reg_val > LIS2DW12_ODR_200HZ_VAL) - ret = set_power_mode(s, LIS2DW12_HIGH_PERF, 0); - else - ret = set_power_mode(s, LIS2DW12_LOW_POWER, - LIS2DW12_LOW_POWER_MODE_2); -#endif - - ret = st_write_data_with_mask(s, LIS2DW12_ACC_ODR_ADDR, - LIS2DW12_ACC_ODR_MASK, reg_val); - if (ret == EC_SUCCESS) - data->base.odr = normalized_rate; - -#if defined(CONFIG_ACCEL_FIFO) && defined(CONFIG_ACCEL_LIS2DW_AS_BASE) - /* FIFO restart collecting events in continuous mode. */ - ret = lis2dw12_enable_fifo(s, LIS2DW12_FIFO_CONT_MODE); -#endif /* CONFIG_ACCEL_FIFO && CONFIG_ACCEL_LIS2DW_AS_BASE */ - -unlock_rate: - mutex_unlock(s->mutex); - - return ret; -} - -static int is_data_ready(const struct motion_sensor_t *s, int *ready) -{ - int ret, tmp; - - ret = st_raw_read8(s->port, s->i2c_spi_addr_flags, - LIS2DW12_STATUS_REG, &tmp); - if (ret != EC_SUCCESS) - return ret; - - *ready = (LIS2DW12_STS_DRDY_UP == (tmp & LIS2DW12_STS_DRDY_UP)); - - return EC_SUCCESS; -} - -static int read(const struct motion_sensor_t *s, intv3_t v) -{ - uint8_t raw[OUT_XYZ_SIZE]; - int ret, tmp = 0; - - ret = is_data_ready(s, &tmp); - if (ret != EC_SUCCESS) - return ret; - - /* - * If sensor data is not ready, return the previous read data. - * Note: return success so that motion senor task can read again - * to get the latest updated sensor data quickly. - */ - if (!tmp) { - if (v != s->raw_xyz) - memcpy(v, s->raw_xyz, sizeof(s->raw_xyz)); - return EC_SUCCESS; - } - - /* Read 6 bytes starting at xyz_reg. */ - ret = st_raw_read_n_noinc(s->port, s->i2c_spi_addr_flags, - LIS2DW12_OUT_X_L_ADDR, raw, - OUT_XYZ_SIZE); - if (ret != EC_SUCCESS) { - CPRINTS("%s type:0x%X RD XYZ Error", s->name, s->type); - return ret; - } - - /* Transform from LSB to real data with rotation and gain. */ - st_normalize(s, v, raw); - - return EC_SUCCESS; -} - -static int init(const struct motion_sensor_t *s) -{ - int ret = 0, tmp, timeout = 0, status; - struct stprivate_data *data = s->drv_data; - - ret = st_raw_read8(s->port, s->i2c_spi_addr_flags, - LIS2DW12_WHO_AM_I_REG, &tmp); - if (ret != EC_SUCCESS) - return EC_ERROR_UNKNOWN; - - if (tmp != LIS2DW12_WHO_AM_I) - return EC_ERROR_ACCESS_DENIED; - - /* - * This sensor can be powered through an EC reboot, so the state of - * the sensor is unknown here. Initiate software reset to restore - * sensor to default. - */ - mutex_lock(s->mutex); - ret = st_raw_write8(s->port, s->i2c_spi_addr_flags, - LIS2DW12_SOFT_RESET_ADDR, LIS2DW12_SOFT_RESET_MASK); - if (ret != EC_SUCCESS) - goto err_unlock; - - /* Wait End of Reset. */ - do { - if (timeout > 10) { - ret = EC_RES_TIMEOUT; - goto err_unlock; - } - - msleep(1); - timeout += 1; - ret = st_raw_read8(s->port, s->i2c_spi_addr_flags, - LIS2DW12_SOFT_RESET_ADDR, &status); - if (ret != EC_SUCCESS) - continue; - } while ((status & LIS2DW12_SOFT_RESET_MASK) != 0); - - /* Enable BDU. */ - ret = st_write_data_with_mask(s, LIS2DW12_BDU_ADDR, LIS2DW12_BDU_MASK, - LIS2DW12_EN_BIT); - if (ret != EC_SUCCESS) - goto err_unlock; - - ret = st_write_data_with_mask(s, LIS2DW12_LIR_ADDR, LIS2DW12_LIR_MASK, - LIS2DW12_EN_BIT); - if (ret != EC_SUCCESS) - goto err_unlock; - -#if defined(CONFIG_ACCEL_INTERRUPTS) && defined(CONFIG_ACCEL_LIS2DW_AS_BASE) - /* Interrupt trigger level of power-on-reset is HIGH */ - if (!(MOTIONSENSE_FLAG_INT_ACTIVE_HIGH & s->flags)) { - ret = st_write_data_with_mask(s, LIS2DW12_H_ACTIVE_ADDR, - LIS2DW12_H_ACTIVE_MASK, - LIS2DW12_EN_BIT); - if (ret != EC_SUCCESS) - goto err_unlock; - } -#endif - -#ifdef CONFIG_ACCEL_LIS2DWL - /* lis2dwl supports 14 bit resolution only at high perfomance mode */ - ret = set_power_mode(s, LIS2DW12_HIGH_PERF, 0); -#else - /* Set default Mode and Low Power Mode. */ - ret = set_power_mode(s, LIS2DW12_LOW_POWER, LIS2DW12_LOW_POWER_MODE_2); -#endif - if (ret != EC_SUCCESS) - goto err_unlock; - -#ifdef CONFIG_ACCEL_LIS2DW_AS_BASE - if (IS_ENABLED(CONFIG_ACCEL_INTERRUPTS)) { - ret = lis2dw12_config_interrupt(s); - if (ret != EC_SUCCESS) - goto err_unlock; - } -#endif - mutex_unlock(s->mutex); - - /* Set default resolution. */ - data->resol = LIS2DW12_RESOLUTION; - return sensor_init_done(s); - -err_unlock: - mutex_unlock(s->mutex); - CPRINTS("%s: MS Init type:0x%X Error", s->name, s->type); - return EC_ERROR_UNKNOWN; -} - -const struct accelgyro_drv lis2dw12_drv = { - .init = init, - .read = read, - .set_range = set_range, - .get_range = get_range, - .get_resolution = st_get_resolution, - .set_data_rate = set_data_rate, - .get_data_rate = st_get_data_rate, - .set_offset = st_set_offset, - .get_offset = st_get_offset, -#if defined(CONFIG_ACCEL_INTERRUPTS) && defined(CONFIG_ACCEL_LIS2DW_AS_BASE) - .irq_handler = lis2dw12_irq_handler, -#endif /* CONFIG_ACCEL_INTERRUPTS && CONFIG_ACCEL_LIS2DW_AS_BASE */ -}; diff --git a/driver/accel_lis2dw12.h b/driver/accel_lis2dw12.h deleted file mode 100644 index 225af1b748..0000000000 --- a/driver/accel_lis2dw12.h +++ /dev/null @@ -1,229 +0,0 @@ -/* Copyright 2019 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. - */ - -/* - * LIS2DW12 accelerometer include file for Chrome EC 3D digital accelerometer. - * For more details on LIS2DW12 device please refer to www.st.com. - */ - -#ifndef __CROS_EC_ACCEL_LIS2DW12_H -#define __CROS_EC_ACCEL_LIS2DW12_H - -#include "driver/stm_mems_common.h" - -/* - * 7-bit address is 011000Xb. Where 'X' is determined - * by the voltage on the ADDR pin. - */ -#define LIS2DW12_ADDR0 0x18 -#define LIS2DW12_ADDR1 0x19 - -#define LIS2DWL_ADDR0_FLAGS 0x18 -#define LIS2DWL_ADDR1_FLAGS 0x19 - -#define LIS2DW12_EN_BIT 0x01 -#define LIS2DW12_DIS_BIT 0x00 - -/* Who am I. */ -#define LIS2DW12_WHO_AM_I_REG 0x0f -#define LIS2DW12_WHO_AM_I 0x44 - -/* Registers sensor. */ -#define LIS2DW12_CTRL1_ADDR 0x20 -#define LIS2DW12_CTRL2_ADDR 0x21 -#define LIS2DW12_CTRL3_ADDR 0x22 - -#define LIS2DW12_CTRL4_ADDR 0x23 - -/* CTRL4 bits. */ -#define LIS2DW12_INT1_FTH 0x02 -#define LIS2DW12_INT1_D_TAP 0x08 -#define LIS2DW12_INT1_S_TAP 0x40 - -#define LIS2DW12_CTRL5_ADDR 0x24 - -/* CTRL5 bits. */ -#define LIS2DW12_INT2_FTH 0x02 - -#define LIS2DW12_CTRL6_ADDR 0x25 -#define LIS2DW12_STATUS_REG 0x27 - -/* STATUS bits. */ -#define LIS2DW12_STS_DRDY_UP 0x01 -#define LIS2DW12_SINGLE_TAP_UP 0x08 -#define LIS2DW12_DOUBLE_TAP_UP 0x10 -#define LIS2DW12_FIFO_THS_UP 0x80 - -#define LIS2DW12_OUT_X_L_ADDR 0x28 - -#define LIS2DW12_FIFO_CTRL_ADDR 0x2e - -/* FIFO_CTRL bits. */ -#define LIS2DW12_FIFO_MODE_MASK 0xe0 - -/* List of supported FIFO mode. */ -enum lis2dw12_fmode { - LIS2DW12_FIFO_BYPASS_MODE = 0, - LIS2DW12_FIFO_MODE, - LIS2DW12_FIFO_CONT_MODE = 6 -}; - -#define LIS2DW12_FIFO_THRESHOLD_MASK 0x1f - -#define LIS2DW12_FIFO_SAMPLES_ADDR 0x2f -#define LIS2DW12_TAP_THS_X_ADDR 0x30 -#define LIS2DW12_TAP_THS_Y_ADDR 0x31 -#define LIS2DW12_TAP_THS_Z_ADDR 0x32 -#define LIS2DW12_INT_DUR_ADDR 0x33 - -#define LIS2DW12_WAKE_UP_THS_ADDR 0x34 - -/* TAP bits. */ -#define LIS2DW12_SINGLE_DOUBLE_TAP 0x80 - -/* FIFO_SAMPLES bits. */ -#define LIS2DW12_FIFO_DIFF_MASK 0x3f -#define LIS2DW12_FIFO_OVR_MASK 0x40 -#define LIS2DW12_FIFO_FTH_MASK 0x80 - -#define LIS2DW12_ABS_INT_CFG_ADDR 0x3f - -/* INT Configuration bits. */ -#define LIS2DW12_DRDY_PULSED 0x80 -#define LIS2DW12_INT2_ON_INT1 0x40 -#define LIS2DW12_INT_ENABLE 0x20 - -/* Alias Registers/Masks. */ -#define LIS2DW12_ACC_ODR_ADDR LIS2DW12_CTRL1_ADDR -#define LIS2DW12_ACC_ODR_MASK 0xf0 - -#define LIS2DW12_ACC_MODE_ADDR LIS2DW12_CTRL1_ADDR -#define LIS2DW12_ACC_MODE_MASK 0x0c - -/* Power mode selection. */ -enum lis2sw12_mode { - LIS2DW12_LOW_POWER = 0, - LIS2DW12_HIGH_PERF, - LIS2DW12_SINGLE_DC, - LIS2DW12_LOW_POWER_LIST_NUM -}; - -#define LIS2DW12_ACC_LPMODE_ADDR LIS2DW12_CTRL1_ADDR -#define LIS2DW12_ACC_LPMODE_MASK 0x03 - -/* - * Low power mode selection. - * TODO: Support all Low Power Mode. Actually is not supported only - * LOW_POWER_MODE_1. - */ -enum lis2sw12_lpmode { - LIS2DW12_LOW_POWER_MODE_1 = 0, - LIS2DW12_LOW_POWER_MODE_2, - LIS2DW12_LOW_POWER_MODE_3, - LIS2DW12_LOW_POWER_MODE_4, - LIS2DW12_LOW_POWER_MODE_LIST_NUM -}; - -#define LIS2DW12_BDU_ADDR LIS2DW12_CTRL2_ADDR -#define LIS2DW12_BDU_MASK 0x08 - -#define LIS2DW12_SOFT_RESET_ADDR LIS2DW12_CTRL2_ADDR -#define LIS2DW12_SOFT_RESET_MASK 0x40 - -#define LIS2DW12_BOOT_ADDR LIS2DW12_CTRL2_ADDR -#define LIS2DW12_BOOT_MASK 0x80 - -#define LIS2DW12_LIR_ADDR LIS2DW12_CTRL3_ADDR -#define LIS2DW12_LIR_MASK 0x10 - -#define LIS2DW12_H_ACTIVE_ADDR LIS2DW12_CTRL3_ADDR -#define LIS2DW12_H_ACTIVE_MASK 0x08 - -#define LIS2DW12_INT1_FTH_ADDR LIS2DW12_CTRL4_ADDR -#define LIS2DW12_INT1_FTH_MASK LIS2DW12_INT1_FTH - -#define LIS2DW12_INT1_TAP_ADDR LIS2DW12_CTRL4_ADDR -#define LIS2DW12_INT1_DTAP_MASK 0x08 -#define LIS2DW12_INT1_STAP_MASK 0x40 - -#define LIS2DW12_INT1_D_TAP_EN LIS2DW12_INT1_DTAP_MASK - -#define LIS2DW12_STATUS_TAP LIS2DW12_STS_DRDY_UP -#define LIS2DW12_SINGLE_TAP LIS2DW12_SINGLE_TAP_UP -#define LIS2DW12_DOUBLE_TAP LIS2DW12_DOUBLE_TAP_UP - -#define LIS2DW12_INT2_ON_INT1_ADDR LIS2DW12_ABS_INT_CFG_ADDR -#define LIS2DW12_INT2_ON_INT1_MASK LIS2DW12_INT2_ON_INT1 - -#define LIS2DW12_DRDY_PULSED_ADDR LIS2DW12_ABS_INT_CFG_ADDR -#define LIS2DW12_DRDY_PULSED_MASK LIS2DW12_DRDY_PULSED - -/* Acc data rate for HR mode. */ -enum lis2dw12_odr { - LIS2DW12_ODR_POWER_OFF_VAL = 0x00, - LIS2DW12_ODR_12HZ_VAL = 0x02, - LIS2DW12_ODR_25HZ_VAL, - LIS2DW12_ODR_50HZ_VAL, - LIS2DW12_ODR_100HZ_VAL, - LIS2DW12_ODR_200HZ_VAL, - LIS2DW12_ODR_400HZ_VAL, - LIS2DW12_ODR_800HZ_VAL, - LIS2DW12_ODR_1_6kHZ_VAL, - LIS2DW12_ODR_LIST_NUM -}; - -/* Absolute Acc rate. */ -#define LIS2DW12_ODR_MIN_VAL 12500 -#define LIS2DW12_ODR_MAX_VAL 1600000 - -/* Full scale range registers. */ -#define LIS2DW12_FS_ADDR LIS2DW12_CTRL6_ADDR -#define LIS2DW12_FS_MASK 0x30 - -/* Acc FS value. */ -enum lis2dw12_fs { - LIS2DW12_FS_2G_VAL = 0x00, - LIS2DW12_FS_4G_VAL, - LIS2DW12_FS_8G_VAL, - LIS2DW12_FS_16G_VAL, - LIS2DW12_FS_LIST_NUM -}; - -#define LIS2DW12_ACCEL_FS_MAX_VAL 16 - -/* Acc Gain value. */ -#define LIS2DW12_FS_2G_GAIN 3904 -#define LIS2DW12_FS_4G_GAIN (LIS2DW12_FS_2G_GAIN << 1) -#define LIS2DW12_FS_8G_GAIN (LIS2DW12_FS_2G_GAIN << 2) -#define LIS2DW12_FS_16G_GAIN (LIS2DW12_FS_2G_GAIN << 3) - -/* FS Full Scale value from Gain. */ -#define LIS2DW12_GAIN_FS(_gain) \ - (2 << (31 - __builtin_clz(_gain / LIS2DW12_FS_2G_GAIN))) - -/* Gain value from selected Full Scale. */ -#define LIS2DW12_FS_GAIN(_fs) \ - (LIS2DW12_FS_2G_GAIN << (30 - __builtin_clz(_fs))) - -/* Reg value from Full Scale. */ -#define LIS2DW12_FS_REG(_fs) \ - (30 - __builtin_clz(_fs)) - -/* Normalized FS value from Full Scale. */ -#define LIS2DW12_NORMALIZE_FS(_fs) \ - (1 << (30 - __builtin_clz(_fs))) - -/* - * Sensor resolution in number of bits. - * Sensor driver support 14 bits resolution. - * TODO: Support all "LP Power Mode" (res. 12/14 bits). - */ -#define LIS2DW12_RESOLUTION 14 - -extern const struct accelgyro_drv lis2dw12_drv; - -void lis2dw12_interrupt(enum gpio_signal signal); - -#endif /* __CROS_EC_ACCEL_LIS2DW12_H */ diff --git a/driver/accelgyro_bmi160.c b/driver/accelgyro_bmi160.c deleted file mode 100644 index e46a367b6a..0000000000 --- a/driver/accelgyro_bmi160.c +++ /dev/null @@ -1,1488 +0,0 @@ -/* 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. - */ - -/** - * BMI160 accelerometer and gyro module for Chrome EC - * 3D digital accelerometer & 3D digital gyroscope - */ - -#include "accelgyro.h" -#include "common.h" -#include "console.h" -#include "driver/accelgyro_bmi160.h" -#include "driver/mag_bmm150.h" -#include "hooks.h" -#include "hwtimer.h" -#include "i2c.h" -#include "math_util.h" -#include "motion_sense_fifo.h" -#include "spi.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) - -STATIC_IF(CONFIG_ACCEL_FIFO) volatile uint32_t last_interrupt_timestamp; - -/* - * Struct for pairing an engineering value with the register value for a - * parameter. - */ -struct accel_param_pair { - int val; /* Value in engineering units. */ - int reg_val; /* Corresponding register value. */ -}; - -/* List of range values in +/-G's and their associated register values. */ -static const struct accel_param_pair g_ranges[] = { - {2, BMI160_GSEL_2G}, - {4, BMI160_GSEL_4G}, - {8, BMI160_GSEL_8G}, - {16, BMI160_GSEL_16G} -}; - -/* - * List of angular rate range values in +/-dps's - * and their associated register values. - */ -const struct accel_param_pair dps_ranges[] = { - {125, BMI160_DPS_SEL_125}, - {250, BMI160_DPS_SEL_250}, - {500, BMI160_DPS_SEL_500}, - {1000, BMI160_DPS_SEL_1000}, - {2000, BMI160_DPS_SEL_2000} -}; - -static int wakeup_time[] = { - [MOTIONSENSE_TYPE_ACCEL] = 4, - [MOTIONSENSE_TYPE_GYRO] = 80, - [MOTIONSENSE_TYPE_MAG] = 1 -}; - -static inline const struct accel_param_pair *get_range_table( - enum motionsensor_type type, int *psize) -{ - if (MOTIONSENSE_TYPE_ACCEL == type) { - if (psize) - *psize = ARRAY_SIZE(g_ranges); - return g_ranges; - } else { - if (psize) - *psize = ARRAY_SIZE(dps_ranges); - return dps_ranges; - } -} - -static inline int get_xyz_reg(enum motionsensor_type type) -{ - switch (type) { - case MOTIONSENSE_TYPE_ACCEL: - return BMI160_ACC_X_L_G; - case MOTIONSENSE_TYPE_GYRO: - return BMI160_GYR_X_L_G; - case MOTIONSENSE_TYPE_MAG: - return BMI160_MAG_X_L_G; - default: - return -1; - } -} - -/** - * @return reg value that matches the given engineering value passed in. - * The round_up flag is used to specify whether to round up or down. - * Note, this function always returns a valid reg value. If the request is - * outside the range of values, it returns the closest valid reg value. - */ -static int get_reg_val(const int eng_val, const int round_up, - const struct accel_param_pair *pairs, const int size) -{ - int i; - - for (i = 0; i < size - 1; i++) { - if (eng_val <= pairs[i].val) - break; - - if (eng_val < pairs[i+1].val) { - if (round_up) - i += 1; - break; - } - } - return pairs[i].reg_val; -} - -/** - * @return engineering value that matches the given reg val - */ -static int get_engineering_val(const int reg_val, - const struct accel_param_pair *pairs, const int size) -{ - int i; - - for (i = 0; i < size; i++) { - if (reg_val == pairs[i].reg_val) - break; - } - return pairs[i].val; -} - -#ifdef CONFIG_SPI_ACCEL_PORT -static inline int spi_raw_read(const int addr, const uint8_t reg, - uint8_t *data, const int len) -{ - uint8_t cmd = 0x80 | reg; - - return spi_transaction(&spi_devices[addr], &cmd, 1, data, len); -} -#endif -/** - * Read 8bit register from accelerometer. - */ -static int raw_read8(const int port, - const uint16_t i2c_spi_addr_flags, - const int reg, int *data_ptr) -{ - int rv = -EC_ERROR_PARAM1; - - if (SLAVE_IS_SPI(i2c_spi_addr_flags)) { -#ifdef CONFIG_SPI_ACCEL_PORT - uint8_t val; - rv = spi_raw_read(SLAVE_GET_SPI_ADDR(i2c_spi_addr_flags), - reg, &val, 1); - if (rv == EC_SUCCESS) - *data_ptr = val; -#endif - } else { -#ifdef I2C_PORT_ACCEL - rv = i2c_read8(port, i2c_spi_addr_flags, - reg, data_ptr); -#endif - } - return rv; -} - -/** - * Write 8bit register from accelerometer. - */ -static int raw_write8(const int port, - const uint16_t i2c_spi_addr_flags, - const int reg, int data) -{ - int rv = -EC_ERROR_PARAM1; - - if (SLAVE_IS_SPI(i2c_spi_addr_flags)) { -#ifdef CONFIG_SPI_ACCEL_PORT - uint8_t cmd[2] = { reg, data }; - rv = spi_transaction( - &spi_devices[SLAVE_GET_SPI_ADDR(i2c_spi_addr_flags)], - cmd, 2, NULL, 0); -#endif - } else { -#ifdef I2C_PORT_ACCEL - rv = i2c_write8(port, i2c_spi_addr_flags, - reg, data); -#endif - } - /* - * From Bosch: BMI160 needs a delay of 450us after each write if it - * is in suspend mode, otherwise the operation may be ignored by - * the sensor. Given we are only doing write during init, add - * the delay inconditionally. - */ - msleep(1); - return rv; -} - -#ifdef CONFIG_ACCEL_INTERRUPTS -/** - * Read 32bit register from accelerometer. - */ -static int raw_read32(const int port, - const uint16_t i2c_spi_addr_flags, - const uint8_t reg, int *data_ptr) -{ - int rv = -EC_ERROR_PARAM1; - if (SLAVE_IS_SPI(i2c_spi_addr_flags)) { -#ifdef CONFIG_SPI_ACCEL_PORT - rv = spi_raw_read(SLAVE_GET_SPI_ADDR(i2c_spi_addr_flags), - reg, (uint8_t *)data_ptr, 4); -#endif - } else { -#ifdef I2C_PORT_ACCEL - rv = i2c_read32(port, i2c_spi_addr_flags, - reg, data_ptr); -#endif - } - return rv; -} -#endif /* defined(CONFIG_ACCEL_INTERRUPTS) */ - -/** - * Read n bytes from accelerometer. - */ -static int raw_read_n(const int port, - const uint16_t i2c_spi_addr_flags, - const uint8_t reg, uint8_t *data_ptr, const int len) -{ - int rv = -EC_ERROR_PARAM1; - - if (SLAVE_IS_SPI(i2c_spi_addr_flags)) { -#ifdef CONFIG_SPI_ACCEL_PORT - rv = spi_raw_read(SLAVE_GET_SPI_ADDR(i2c_spi_addr_flags), - reg, data_ptr, len); -#endif - } else { -#ifdef I2C_PORT_ACCEL - rv = i2c_read_block(port, i2c_spi_addr_flags, - reg, data_ptr, len); -#endif - } - return rv; -} - -#ifdef CONFIG_BMI160_SEC_I2C -/** - * Control access to the compass on the secondary i2c interface: - * enable values are: - * 1: manual access, we can issue i2c to the compass - * 0: data access: BMI160 gather data periodically from the compass. - */ -static int bmi160_sec_access_ctrl(const int port, - const uint16_t i2c_spi_addr_flags, - const int enable) -{ - int mag_if_ctrl; - raw_read8(port, i2c_spi_addr_flags, - BMI160_MAG_IF_1, &mag_if_ctrl); - if (enable) { - mag_if_ctrl |= BMI160_MAG_MANUAL_EN; - mag_if_ctrl &= ~BMI160_MAG_READ_BURST_MASK; - mag_if_ctrl |= BMI160_MAG_READ_BURST_1; - } else { - mag_if_ctrl &= ~BMI160_MAG_MANUAL_EN; - mag_if_ctrl &= ~BMI160_MAG_READ_BURST_MASK; - mag_if_ctrl |= BMI160_MAG_READ_BURST_8; - } - return raw_write8(port, i2c_spi_addr_flags, - BMI160_MAG_IF_1, mag_if_ctrl); -} - -/** - * Read register from compass. - * Assuming we are in manual access mode, read compass i2c register. - */ -int bmi160_sec_raw_read8(const int port, - const uint16_t i2c_spi_addr_flags, - const uint8_t reg, int *data_ptr) -{ - /* Only read 1 bytes */ - raw_write8(port, i2c_spi_addr_flags, - BMI160_MAG_I2C_READ_ADDR, reg); - return raw_read8(port, i2c_spi_addr_flags, - BMI160_MAG_I2C_READ_DATA, data_ptr); -} - -/** - * Write register from compass. - * Assuming we are in manual access mode, write to compass i2c register. - */ -int bmi160_sec_raw_write8(const int port, - const uint16_t i2c_spi_addr_flags, - const uint8_t reg, int data) -{ - raw_write8(port, i2c_spi_addr_flags, - BMI160_MAG_I2C_WRITE_DATA, data); - return raw_write8(port, i2c_spi_addr_flags, - BMI160_MAG_I2C_WRITE_ADDR, reg); -} -#endif - -static int enable_fifo(const struct motion_sensor_t *s, int enable) -{ - struct bmi160_drv_data_t *data = BMI160_GET_DATA(s); - int ret, val; - - if (enable) { - /* FIFO start collecting events */ - ret = raw_read8(s->port, s->i2c_spi_addr_flags, - BMI160_FIFO_CONFIG_1, &val); - val |= BMI160_FIFO_SENSOR_EN(s->type); - ret = raw_write8(s->port, s->i2c_spi_addr_flags, - BMI160_FIFO_CONFIG_1, val); - if (ret == EC_SUCCESS) - data->flags |= 1 << (s->type + BMI160_FIFO_FLAG_OFFSET); - - } else { - /* FIFO stop collecting events */ - ret = raw_read8(s->port, s->i2c_spi_addr_flags, - BMI160_FIFO_CONFIG_1, &val); - val &= ~BMI160_FIFO_SENSOR_EN(s->type); - ret = raw_write8(s->port, s->i2c_spi_addr_flags, - BMI160_FIFO_CONFIG_1, val); - if (ret == EC_SUCCESS) - data->flags &= - ~(1 << (s->type + BMI160_FIFO_FLAG_OFFSET)); - } - return ret; -} - -static int set_range(const struct motion_sensor_t *s, - int range, - int rnd) -{ - int ret, range_tbl_size; - uint8_t reg_val, ctrl_reg; - const struct accel_param_pair *ranges; - struct accelgyro_saved_data_t *data = BMI160_GET_SAVED_DATA(s); - - if (s->type == MOTIONSENSE_TYPE_MAG) { - data->range = range; - return EC_SUCCESS; - } - - ctrl_reg = BMI160_RANGE_REG(s->type); - ranges = get_range_table(s->type, &range_tbl_size); - reg_val = get_reg_val(range, rnd, ranges, range_tbl_size); - - ret = raw_write8(s->port, s->i2c_spi_addr_flags, - ctrl_reg, reg_val); - /* Now that we have set the range, update the driver's value. */ - if (ret == EC_SUCCESS) - data->range = get_engineering_val(reg_val, ranges, - range_tbl_size); - return ret; -} - -static int get_range(const struct motion_sensor_t *s) -{ - struct accelgyro_saved_data_t *data = BMI160_GET_SAVED_DATA(s); - - return data->range; -} - -static int get_resolution(const struct motion_sensor_t *s) -{ - return BMI160_RESOLUTION; -} - -static int set_data_rate(const struct motion_sensor_t *s, - int rate, - int rnd) -{ - int ret, val, normalized_rate; - uint8_t ctrl_reg, reg_val; - struct accelgyro_saved_data_t *data = BMI160_GET_SAVED_DATA(s); -#ifdef CONFIG_MAG_BMI160_BMM150 - struct mag_cal_t *moc = BMM150_CAL(s); -#endif - - if (rate == 0) { - /* FIFO stop collecting events */ - if (IS_ENABLED(CONFIG_ACCEL_FIFO)) - enable_fifo(s, 0); - - /* go to suspend mode */ - ret = raw_write8(s->port, s->i2c_spi_addr_flags, - BMI160_CMD_REG, - BMI160_CMD_MODE_SUSPEND(s->type)); - msleep(3); - data->odr = 0; -#ifdef CONFIG_MAG_BMI160_BMM150 - if (s->type == MOTIONSENSE_TYPE_MAG) - moc->batch_size = 0; -#endif - return ret; - } else if (data->odr == 0) { - /* back from suspend mode. */ - ret = raw_write8(s->port, s->i2c_spi_addr_flags, - BMI160_CMD_REG, - BMI160_CMD_MODE_NORMAL(s->type)); - msleep(wakeup_time[s->type]); - } - ctrl_reg = BMI160_CONF_REG(s->type); - reg_val = BMI160_ODR_TO_REG(rate); - normalized_rate = BMI160_REG_TO_ODR(reg_val); - if (rnd && (normalized_rate < rate)) { - reg_val++; - normalized_rate = BMI160_REG_TO_ODR(reg_val); - } - - switch (s->type) { - case MOTIONSENSE_TYPE_ACCEL: - if (normalized_rate > BMI160_ACCEL_MAX_FREQ || - normalized_rate < BMI160_ACCEL_MIN_FREQ) - return EC_RES_INVALID_PARAM; - break; - case MOTIONSENSE_TYPE_GYRO: - if (normalized_rate > BMI160_GYRO_MAX_FREQ || - normalized_rate < BMI160_GYRO_MIN_FREQ) - return EC_RES_INVALID_PARAM; - break; -#ifdef CONFIG_MAG_BMI160_BMM150 - case MOTIONSENSE_TYPE_MAG: - /* We use the regular preset we can go about 100Hz */ - if (reg_val > BMI160_ODR_100HZ || reg_val < BMI160_ODR_0_78HZ) - return EC_RES_INVALID_PARAM; - break; -#endif - - default: - return EC_RES_INVALID_PARAM; - } - - /* - * Lock accel resource to prevent another task from attempting - * to write accel parameters until we are done. - */ - mutex_lock(s->mutex); - - ret = raw_read8(s->port, s->i2c_spi_addr_flags, ctrl_reg, &val); - if (ret != EC_SUCCESS) - goto accel_cleanup; - - val = (val & ~BMI160_ODR_MASK) | reg_val; - ret = raw_write8(s->port, s->i2c_spi_addr_flags, ctrl_reg, val); - if (ret != EC_SUCCESS) - goto accel_cleanup; - - /* Now that we have set the odr, update the driver's value. */ - data->odr = normalized_rate; - -#ifdef CONFIG_MAG_BMI160_BMM150 - if (s->type == MOTIONSENSE_TYPE_MAG) { - /* Reset the calibration */ - init_mag_cal(moc); - /* - * We need at least MIN_BATCH_SIZE amd we must have collected - * for at least MIN_BATCH_WINDOW_US. - * Given odr is in mHz, multiply by 1000x - */ - moc->batch_size = MAX( - MAG_CAL_MIN_BATCH_SIZE, - (data->odr * 1000) / (MAG_CAL_MIN_BATCH_WINDOW_US)); - CPRINTS("Batch size: %d", moc->batch_size); - } -#endif - - /* - * FIFO start collecting events. - * They will be discarded if AP does not want them. - */ - if (IS_ENABLED(CONFIG_ACCEL_FIFO)) - enable_fifo(s, 1); - -accel_cleanup: - mutex_unlock(s->mutex); - return ret; -} - -static int get_data_rate(const struct motion_sensor_t *s) -{ - struct accelgyro_saved_data_t *data = BMI160_GET_SAVED_DATA(s); - - return data->odr; -} -static int get_offset(const struct motion_sensor_t *s, - int16_t *offset, - int16_t *temp) -{ - int i, val, val98; - intv3_t v; - - switch (s->type) { - case MOTIONSENSE_TYPE_ACCEL: - /* - * The offset of the accelerometer off_acc_[xyz] is a 8 bit - * two-complement number in units of 3.9 mg independent of the - * range selected for the accelerometer. - */ - for (i = X; i <= Z; i++) { - raw_read8(s->port, s->i2c_spi_addr_flags, - BMI160_OFFSET_ACC70 + i, &val); - if (val > 0x7f) - val = -256 + val; - v[i] = val * BMI160_OFFSET_ACC_MULTI_MG / - BMI160_OFFSET_ACC_DIV_MG; - } - break; - case MOTIONSENSE_TYPE_GYRO: - /* Read the MSB first */ - raw_read8(s->port, s->i2c_spi_addr_flags, - BMI160_OFFSET_EN_GYR98, &val98); - /* - * The offset of the gyroscope off_gyr_[xyz] is a 10 bit - * two-complement number in units of 0.061 °/s. - * Therefore a maximum range that can be compensated is - * -31.25 °/s to +31.25 °/s - */ - for (i = X; i <= Z; i++) { - raw_read8(s->port, s->i2c_spi_addr_flags, - BMI160_OFFSET_GYR70 + i, &val); - val |= ((val98 >> (2 * i)) & 0x3) << 8; - if (val > 0x1ff) - val = -1024 + val; - v[i] = val * BMI160_OFFSET_GYRO_MULTI_MDS / - BMI160_OFFSET_GYRO_DIV_MDS; - } - break; -#ifdef CONFIG_MAG_BMI160_BMM150 - case MOTIONSENSE_TYPE_MAG: - bmm150_get_offset(s, v); - break; -#endif /* defined(CONFIG_MAG_BMI160_BMM150) */ - default: - for (i = X; i <= Z; i++) - v[i] = 0; - } - rotate(v, *s->rot_standard_ref, v); - offset[X] = v[X]; - offset[Y] = v[Y]; - offset[Z] = v[Z]; - /* Saving temperature at calibration not supported yet */ - *temp = EC_MOTION_SENSE_INVALID_CALIB_TEMP; - return EC_SUCCESS; -} - -static int set_offset(const struct motion_sensor_t *s, - const int16_t *offset, - int16_t temp) -{ - int ret, i, val, val98; - intv3_t v = { offset[X], offset[Y], offset[Z] }; - - rotate_inv(v, *s->rot_standard_ref, v); - - ret = raw_read8(s->port, s->i2c_spi_addr_flags, - BMI160_OFFSET_EN_GYR98, &val98); - if (ret != 0) - return ret; - - switch (s->type) { - case MOTIONSENSE_TYPE_ACCEL: - for (i = X; i <= Z; i++) { - val = v[i] * BMI160_OFFSET_ACC_DIV_MG / - BMI160_OFFSET_ACC_MULTI_MG; - if (val > 127) - val = 127; - if (val < -128) - val = -128; - if (val < 0) - val = 256 + val; - raw_write8(s->port, s->i2c_spi_addr_flags, - BMI160_OFFSET_ACC70 + i, val); - } - ret = raw_write8(s->port, s->i2c_spi_addr_flags, - BMI160_OFFSET_EN_GYR98, - val98 | BMI160_OFFSET_ACC_EN); - break; - case MOTIONSENSE_TYPE_GYRO: - for (i = X; i <= Z; i++) { - val = v[i] * BMI160_OFFSET_GYRO_DIV_MDS / - BMI160_OFFSET_GYRO_MULTI_MDS; - if (val > 511) - val = 511; - if (val < -512) - val = -512; - if (val < 0) - val = 1024 + val; - raw_write8(s->port, s->i2c_spi_addr_flags, - BMI160_OFFSET_GYR70 + i, val & 0xFF); - val98 &= ~(0x3 << (2 * i)); - val98 |= (val >> 8) << (2 * i); - } - ret = raw_write8(s->port, s->i2c_spi_addr_flags, - BMI160_OFFSET_EN_GYR98, - val98 | BMI160_OFFSET_GYRO_EN); - break; -#ifdef CONFIG_MAG_BMI160_BMM150 - case MOTIONSENSE_TYPE_MAG: - ret = bmm150_set_offset(s, v); - break; -#endif /* defined(CONFIG_MAG_BMI160) */ - default: - ret = EC_RES_INVALID_PARAM; - } - return ret; -} - -int set_scale(const struct motion_sensor_t *s, - const uint16_t *scale, int16_t temp) -{ - struct accelgyro_saved_data_t *data = BMI160_GET_SAVED_DATA(s); - - data->scale[X] = scale[X]; - data->scale[Y] = scale[Y]; - data->scale[Z] = scale[Z]; - return EC_SUCCESS; -} - -int get_scale(const struct motion_sensor_t *s, - uint16_t *scale, int16_t *temp) -{ - struct accelgyro_saved_data_t *data = BMI160_GET_SAVED_DATA(s); - - scale[X] = data->scale[X]; - scale[Y] = data->scale[Y]; - scale[Z] = data->scale[Z]; - *temp = EC_MOTION_SENSE_INVALID_CALIB_TEMP; - return EC_SUCCESS; -} - -static int perform_calib(const struct motion_sensor_t *s, int enable) -{ - int ret, val, en_flag, status, rate; - timestamp_t deadline; - - if (!enable) - return EC_SUCCESS; - - rate = get_data_rate(s); - /* - * Temporary set frequency to 100Hz to get enough data in a short - * period of time. - */ - set_data_rate(s, 100000, 0); - - switch (s->type) { - case MOTIONSENSE_TYPE_ACCEL: - /* We assume the device is laying flat for calibration */ - if (s->rot_standard_ref == NULL || - (*s->rot_standard_ref)[2][2] > INT_TO_FP(0)) - val = BMI160_FOC_ACC_PLUS_1G; - else - val = BMI160_FOC_ACC_MINUS_1G; - val = (BMI160_FOC_ACC_0G << BMI160_FOC_ACC_X_OFFSET) | - (BMI160_FOC_ACC_0G << BMI160_FOC_ACC_Y_OFFSET) | - (val << BMI160_FOC_ACC_Z_OFFSET); - en_flag = BMI160_OFFSET_ACC_EN; - break; - case MOTIONSENSE_TYPE_GYRO: - val = BMI160_FOC_GYRO_EN; - en_flag = BMI160_OFFSET_GYRO_EN; - break; - default: - /* Not supported on Magnetometer */ - ret = EC_RES_INVALID_PARAM; - goto end_perform_calib; - } - ret = raw_write8(s->port, s->i2c_spi_addr_flags, - BMI160_FOC_CONF, val); - ret = raw_write8(s->port, s->i2c_spi_addr_flags, - BMI160_CMD_REG, BMI160_CMD_START_FOC); - deadline.val = get_time().val + 400 * MSEC; - do { - if (timestamp_expired(deadline, NULL)) { - ret = EC_RES_TIMEOUT; - goto end_perform_calib; - } - msleep(50); - ret = raw_read8(s->port, s->i2c_spi_addr_flags, - BMI160_STATUS, &status); - if (ret != EC_SUCCESS) - goto end_perform_calib; - } while ((status & BMI160_FOC_RDY) == 0); - - /* Calibration is successful, and loaded, use the result */ - ret = raw_read8(s->port, s->i2c_spi_addr_flags, - BMI160_OFFSET_EN_GYR98, &val); - ret = raw_write8(s->port, s->i2c_spi_addr_flags, - BMI160_OFFSET_EN_GYR98, val | en_flag); -end_perform_calib: - set_data_rate(s, rate, 0); - return ret; -} - -void normalize(const struct motion_sensor_t *s, intv3_t v, uint8_t *input) -{ - int i; - struct accelgyro_saved_data_t *data = BMI160_GET_SAVED_DATA(s); - -#ifdef CONFIG_MAG_BMI160_BMM150 - if (s->type == MOTIONSENSE_TYPE_MAG) - bmm150_normalize(s, v, input); - else -#endif -#ifdef CONFIG_MAG_BMI160_LIS2MDL - if (s->type == MOTIONSENSE_TYPE_MAG) - lis2mdl_normalize(s, v, data); - else -#endif - { - v[0] = ((int16_t)((input[1] << 8) | input[0])); - v[1] = ((int16_t)((input[3] << 8) | input[2])); - v[2] = ((int16_t)((input[5] << 8) | input[4])); - } - rotate(v, *s->rot_standard_ref, v); - for (i = X; i <= Z; i++) - v[i] = SENSOR_APPLY_SCALE(v[i], data->scale[i]); -} - -/* - * Manage gesture recognition. - * Defined even if host interface is not defined, to enable double tap even - * when the host does not deal with gesture. - */ -int manage_activity(const struct motion_sensor_t *s, - enum motionsensor_activity activity, - int enable, - const struct ec_motion_sense_activity *param) -{ - int ret; - struct bmi160_drv_data_t *data = BMI160_GET_DATA(s); - - switch (activity) { -#ifdef CONFIG_GESTURE_SIGMO - case MOTIONSENSE_ACTIVITY_SIG_MOTION: { - int tmp; - ret = raw_read8(s->port, s->addr, BMI160_INT_EN_0, &tmp); - if (ret) - return ret; - if (enable) { - /* We should use parameters from caller */ - raw_write8(s->port, s->i2c_spi_addr_flags, - BMI160_INT_MOTION_3, - BMI160_MOTION_PROOF_TIME( - CONFIG_GESTURE_SIGMO_PROOF_MS) << - BMI160_MOTION_PROOF_OFF | - BMI160_MOTION_SKIP_TIME( - CONFIG_GESTURE_SIGMO_SKIP_MS) << - BMI160_MOTION_SKIP_OFF | - BMI160_MOTION_SIG_MOT_SEL); - raw_write8(s->port, s->i2c_spi_addr_flags, - BMI160_INT_MOTION_1, - BMI160_MOTION_TH(s, - CONFIG_GESTURE_SIGMO_THRES_MG)); - tmp |= BMI160_INT_ANYMO_X_EN | - BMI160_INT_ANYMO_Y_EN | - BMI160_INT_ANYMO_Z_EN; - } else { - tmp &= ~(BMI160_INT_ANYMO_X_EN | - BMI160_INT_ANYMO_Y_EN | - BMI160_INT_ANYMO_Z_EN); - } - ret = raw_write8(s->port, s->i2c_spi_addr_flags, - BMI160_INT_EN_0, tmp); - if (ret) - ret = EC_RES_UNAVAILABLE; - break; - } -#endif -#ifdef CONFIG_GESTURE_SENSOR_DOUBLE_TAP - case MOTIONSENSE_ACTIVITY_DOUBLE_TAP: { - int tmp; - /* Set double tap interrupt */ - ret = raw_read8(s->port, s->i2c_spi_addr_flags, - BMI160_INT_EN_0, &tmp); - if (ret) - return ret; - if (enable) - tmp |= BMI160_INT_D_TAP_EN; - else - tmp &= ~BMI160_INT_D_TAP_EN; - ret = raw_write8(s->port, s->i2c_spi_addr_flags, - BMI160_INT_EN_0, tmp); - if (ret) - ret = EC_RES_UNAVAILABLE; - break; - } -#endif - default: - ret = EC_RES_INVALID_PARAM; - } - if (ret == EC_RES_SUCCESS) { - if (enable) { - data->enabled_activities |= 1 << activity; - data->disabled_activities &= ~BIT(activity); - } else { - data->enabled_activities &= ~BIT(activity); - data->disabled_activities |= 1 << activity; - } - } - return ret; -} - -#ifdef CONFIG_GESTURE_HOST_DETECTION -int list_activities(const struct motion_sensor_t *s, - uint32_t *enabled, - uint32_t *disabled) -{ - struct bmi160_drv_data_t *data = BMI160_GET_DATA(s); - *enabled = data->enabled_activities; - *disabled = data->disabled_activities; - return EC_RES_SUCCESS; -} -#endif - -#ifdef CONFIG_ACCEL_INTERRUPTS - -enum fifo_state { - FIFO_HEADER, - FIFO_DATA_SKIP, - FIFO_DATA_TIME, - FIFO_DATA_CONFIG, -}; - - -#define BMI160_FIFO_BUFFER 64 -static uint8_t bmi160_buffer[BMI160_FIFO_BUFFER]; -/* - * Decode the header from the fifo. - * Return 0 if we need further processing. - * Sensor mutex must be held during processing, to protect the fifos. - * - * @s: base sensor - * @hdr: the header to decode - * @bp: current pointer in the buffer, updated when processing the header. - * @ep: pointer to the end of the valid data in the buffer. - */ -static int bmi160_decode_header(struct motion_sensor_t *accel, - enum fifo_header hdr, uint32_t last_ts, - uint8_t **bp, uint8_t *ep) -{ - if ((hdr & BMI160_FH_MODE_MASK) == BMI160_EMPTY && - (hdr & BMI160_FH_PARM_MASK) != 0) { - int i, size = 0; - /* Check if there is enough space for the data frame */ - for (i = MOTIONSENSE_TYPE_MAG; i >= MOTIONSENSE_TYPE_ACCEL; - i--) { - if (hdr & (1 << (i + BMI160_FH_PARM_OFFSET))) - size += (i == MOTIONSENSE_TYPE_MAG ? 8 : 6); - } - if (*bp + size > ep) { - /* frame is not complete, it will be retransmitted. */ - *bp = ep; - return 1; - } - for (i = MOTIONSENSE_TYPE_MAG; i >= MOTIONSENSE_TYPE_ACCEL; - i--) { - struct motion_sensor_t *s = accel + i; - - if (hdr & (1 << (i + BMI160_FH_PARM_OFFSET))) { - struct ec_response_motion_sensor_data vector; - int *v = s->raw_xyz; - vector.flags = 0; - normalize(s, v, *bp); - if (IS_ENABLED(CONFIG_ACCEL_SPOOF_MODE) && - s->flags & MOTIONSENSE_FLAG_IN_SPOOF_MODE) - v = s->spoof_xyz; - vector.data[X] = v[X]; - vector.data[Y] = v[Y]; - vector.data[Z] = v[Z]; - vector.sensor_num = s - motion_sensors; - motion_sense_fifo_stage_data(&vector, s, 3, - last_ts); - *bp += (i == MOTIONSENSE_TYPE_MAG ? 8 : 6); - } - } - return 1; - } else { - return 0; - } -} - -/** - * Retrieve hardware FIFO from sensor, - * - put data in Sensor Hub fifo. - * - update sensor raw_xyz vector with the last information. - * We put raw data in hub fifo and process data from there. - * @s Pointer to sensor data. - * - * Read only up to bmi160_buffer. If more reads are needed, we will be called - * again by the interrupt routine. - * - * NOTE: If a new driver supports this function, be sure to add a check - * for spoof_mode in order to load the sensor stack with the spoofed - * data. See accelgyro_bmi160.c::load_fifo for an example. - */ -static int load_fifo(struct motion_sensor_t *s, uint32_t last_ts) -{ - struct bmi160_drv_data_t *data = BMI160_GET_DATA(s); - uint16_t length; - enum fifo_state state = FIFO_HEADER; - uint8_t *bp = bmi160_buffer; - uint8_t *ep; - uint32_t beginning; - - - if (s->type != MOTIONSENSE_TYPE_ACCEL) - return EC_SUCCESS; - - if (!(data->flags & - (BMI160_FIFO_ALL_MASK << BMI160_FIFO_FLAG_OFFSET))) { - /* - * The FIFO was disabled while we were processing it. - * - * Flush potential left over: - * When sensor is resumed, we won't read old data. - */ - raw_write8(s->port, s->i2c_spi_addr_flags, - BMI160_CMD_REG, BMI160_CMD_FIFO_FLUSH); - return EC_SUCCESS; - } - - raw_read_n(s->port, s->i2c_spi_addr_flags, - BMI160_FIFO_LENGTH_0, - (uint8_t *)&length, sizeof(length)); - length &= BMI160_FIFO_LENGTH_MASK; - - /* - * We have not requested timestamp, no extra frame to read. - * if we have too much to read, read the whole buffer. - */ - if (length == 0) { - CPRINTS("unexpected empty FIFO"); - return EC_SUCCESS; - } - - /* Add one byte to get an empty FIFO frame.*/ - length++; - - if (length > sizeof(bmi160_buffer)) - CPRINTS("unexpected large FIFO: %d", length); - length = MIN(length, sizeof(bmi160_buffer)); - - - raw_read_n(s->port, s->i2c_spi_addr_flags, - BMI160_FIFO_DATA, bmi160_buffer, length); - beginning = *(uint32_t *)bmi160_buffer; - ep = bmi160_buffer + length; - /* - * FIFO is invalid when reading while the sensors are all - * suspended. - * Instead of returning the empty frame, it can return a - * pattern that looks like a valid header: 84 or 40. - * If we see those, assume the sensors have been disabled - * while this thread was running. - */ - if (beginning == 0x84848484 || - (beginning & 0xdcdcdcdc) == 0x40404040) { - CPRINTS("Suspended FIFO: accel ODR/rate: %d/%d: 0x%08x", - BASE_ODR(s->config[SENSOR_CONFIG_AP].odr), - get_data_rate(s), - beginning); - return EC_SUCCESS; - } - - while (bp < ep) { - switch (state) { - case FIFO_HEADER: { - enum fifo_header hdr = *bp++; - - if (bmi160_decode_header(s, hdr, last_ts, &bp, ep)) - continue; - /* Other cases */ - hdr &= 0xdc; - switch (hdr) { - case BMI160_EMPTY: - return EC_SUCCESS; - case BMI160_SKIP: - state = FIFO_DATA_SKIP; - break; - case BMI160_TIME: - state = FIFO_DATA_TIME; - break; - case BMI160_CONFIG: - state = FIFO_DATA_CONFIG; - break; - default: - CPRINTS("Unknown header: 0x%02x @ %zd", - hdr, bp - bmi160_buffer); - raw_write8(s->port, s->i2c_spi_addr_flags, - BMI160_CMD_REG, - BMI160_CMD_FIFO_FLUSH); - return EC_ERROR_NOT_HANDLED; - } - break; - } - case FIFO_DATA_SKIP: - CPRINTS("@ %zd - %d, skipped %d frames", - bp - bmi160_buffer, length, *bp); - bp++; - state = FIFO_HEADER; - break; - case FIFO_DATA_CONFIG: - CPRINTS("@ %zd - %d, config change: 0x%02x", - bp - bmi160_buffer, length, *bp); - bp++; - state = FIFO_HEADER; - break; - case FIFO_DATA_TIME: - if (bp + 3 > ep) { - bp = ep; - continue; - } - /* We are not requesting timestamp */ - CPRINTS("timestamp %d", (bp[2] << 16) | - (bp[1] << 8) | bp[0]); - state = FIFO_HEADER; - bp += 3; - break; - default: - CPRINTS("Unknown data: 0x%02x", *bp++); - state = FIFO_HEADER; - } - } - return EC_SUCCESS; -} - -/** - * bmi160_interrupt - called when the sensor activates the interrupt line. - * - * This is a "top half" interrupt handler, it just asks motion sense ask - * to schedule the "bottom half", ->irq_handler(). - */ -void bmi160_interrupt(enum gpio_signal signal) -{ - if (IS_ENABLED(CONFIG_ACCEL_FIFO)) - last_interrupt_timestamp = __hw_clock_source_read(); - - task_set_event(TASK_ID_MOTIONSENSE, - CONFIG_ACCELGYRO_BMI160_INT_EVENT, 0); -} - - -static int config_interrupt(const struct motion_sensor_t *s) -{ - int ret, tmp; - - if (s->type != MOTIONSENSE_TYPE_ACCEL) - return EC_SUCCESS; - - mutex_lock(s->mutex); - raw_write8(s->port, s->i2c_spi_addr_flags, - BMI160_CMD_REG, BMI160_CMD_FIFO_FLUSH); - raw_write8(s->port, s->i2c_spi_addr_flags, - BMI160_CMD_REG, BMI160_CMD_INT_RESET); - -#ifdef CONFIG_GESTURE_SENSOR_DOUBLE_TAP - raw_write8(s->port, s->i2c_spi_addr_flags, - BMI160_INT_TAP_0, - BMI160_TAP_DUR(s, CONFIG_GESTURE_TAP_MAX_INTERSTICE_T)); - ret = raw_write8(s->port, s->i2c_spi_addr_flags, - BMI160_INT_TAP_1, - BMI160_TAP_TH(s, CONFIG_GESTURE_TAP_THRES_MG)); -#endif -#ifdef CONFIG_BMI160_ORIENTATION_SENSOR - /* only use orientation sensor on the lid sensor */ - if (s->location == MOTIONSENSE_LOC_LID) { - ret = raw_write8(s->port, s->i2c_spi_addr_flags, - BMI160_INT_ORIENT_0, - BMI160_INT_ORIENT_0_INIT_VAL); - ret = raw_write8(s->port, s->i2c_spi_addr_flags, - BMI160_INT_ORIENT_1, - BMI160_INT_ORIENT_1_INIT_VAL); - } -#endif - -#ifdef CONFIG_ACCELGYRO_BMI160_INT2_OUTPUT - ret = raw_write8(s->port, s->i2c_spi_addr_flags, - BMI160_INT_LATCH, BMI160_LATCH_5MS); -#else - /* Also, configure int2 as an external input. */ - ret = raw_write8(s->port, s->i2c_spi_addr_flags, - BMI160_INT_LATCH, - BMI160_INT2_INPUT_EN | BMI160_LATCH_5MS); -#endif - - /* configure int1 as an interrupt */ - ret = raw_write8(s->port, s->i2c_spi_addr_flags, - BMI160_INT_OUT_CTRL, - BMI160_INT_CTRL(1, OUTPUT_EN)); - - /* Map activity interrupt to int 1 */ - tmp = 0; -#ifdef CONFIG_GESTURE_SIGMO - tmp |= BMI160_INT_ANYMOTION; -#endif -#ifdef CONFIG_GESTURE_SENSOR_DOUBLE_TAP - tmp |= BMI160_INT_D_TAP; -#endif -#ifdef CONFIG_BMI160_ORIENTATION_SENSOR - /* enable orientation interrupt for lid sensor only */ - if (s->location == MOTIONSENSE_LOC_LID) - tmp |= BMI160_INT_ORIENT; -#endif - ret = raw_write8(s->port, s->i2c_spi_addr_flags, - BMI160_INT_MAP_REG(1), tmp); - - if (IS_ENABLED(CONFIG_ACCEL_FIFO)) { - /* map fifo water mark to int 1 */ - ret = raw_write8(s->port, s->i2c_spi_addr_flags, - BMI160_INT_FIFO_MAP, - BMI160_INT_MAP(1, FWM) | - BMI160_INT_MAP(1, FFULL)); - - /* - * Configure fifo watermark to int whenever there's any data in - * there - */ - ret = raw_write8(s->port, s->i2c_spi_addr_flags, - BMI160_FIFO_CONFIG_0, 1); -#ifdef CONFIG_ACCELGYRO_BMI160_INT2_OUTPUT - ret = raw_write8(s->port, s->i2c_spi_addr_flags, - BMI160_FIFO_CONFIG_1, - BMI160_FIFO_HEADER_EN); -#else - ret = raw_write8(s->port, s->i2c_spi_addr_flags, - BMI160_FIFO_CONFIG_1, - BMI160_FIFO_TAG_INT2_EN | - BMI160_FIFO_HEADER_EN); -#endif - - /* Set fifo*/ - ret = raw_read8(s->port, s->i2c_spi_addr_flags, - BMI160_INT_EN_1, &tmp); - tmp |= BMI160_INT_FWM_EN | BMI160_INT_FFUL_EN; - ret = raw_write8(s->port, s->i2c_spi_addr_flags, - BMI160_INT_EN_1, tmp); - } - mutex_unlock(s->mutex); - return ret; -} - -#ifdef CONFIG_BMI160_ORIENTATION_SENSOR -static void irq_set_orientation(struct motion_sensor_t *s, - int interrupt) -{ - int shifted_masked_orientation = - (interrupt >> 24) & BMI160_ORIENT_XY_MASK; - if (BMI160_GET_DATA(s)->raw_orientation != shifted_masked_orientation) { - enum motionsensor_orientation orientation = - MOTIONSENSE_ORIENTATION_UNKNOWN; - - BMI160_GET_DATA(s)->raw_orientation = - shifted_masked_orientation; - - switch (shifted_masked_orientation) { - case BMI160_ORIENT_PORTRAIT: - orientation = MOTIONSENSE_ORIENTATION_PORTRAIT; - break; - case BMI160_ORIENT_PORTRAIT_INVERT: - orientation = - MOTIONSENSE_ORIENTATION_UPSIDE_DOWN_PORTRAIT; - break; - case BMI160_ORIENT_LANDSCAPE: - orientation = MOTIONSENSE_ORIENTATION_LANDSCAPE; - break; - case BMI160_ORIENT_LANDSCAPE_INVERT: - orientation = - MOTIONSENSE_ORIENTATION_UPSIDE_DOWN_LANDSCAPE; - break; - default: - break; - } - orientation = motion_sense_remap_orientation(s, orientation); - SET_ORIENTATION(s, orientation); - } -} -#endif -/** - * 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) -{ - uint32_t interrupt; - int8_t has_read_fifo = 0; - int rv; - - if ((s->type != MOTIONSENSE_TYPE_ACCEL) || - (!(*event & CONFIG_ACCELGYRO_BMI160_INT_EVENT))) - return EC_ERROR_NOT_HANDLED; - - do { - rv = raw_read32(s->port, s->i2c_spi_addr_flags, - BMI160_INT_STATUS_0, &interrupt); - /* - * Bail out of this loop there was an error reading the register - */ - if (rv) - return rv; - -#ifdef CONFIG_GESTURE_SENSOR_DOUBLE_TAP - if (interrupt & BMI160_D_TAP_INT) - *event |= TASK_EVENT_MOTION_ACTIVITY_INTERRUPT( - MOTIONSENSE_ACTIVITY_DOUBLE_TAP); -#endif -#ifdef CONFIG_GESTURE_SIGMO - if (interrupt & BMI160_SIGMOT_INT) - *event |= TASK_EVENT_MOTION_ACTIVITY_INTERRUPT( - MOTIONSENSE_ACTIVITY_SIG_MOTION); -#endif - if (IS_ENABLED(CONFIG_ACCEL_FIFO) && - interrupt & (BMI160_FWM_INT | BMI160_FFULL_INT)) { - load_fifo(s, last_interrupt_timestamp); - has_read_fifo = 1; - } -#ifdef CONFIG_BMI160_ORIENTATION_SENSOR - irq_set_orientation(s, interrupt); -#endif - } while (interrupt != 0); - - if (IS_ENABLED(CONFIG_ACCEL_FIFO) && has_read_fifo) - motion_sense_fifo_commit_data(); - - return EC_SUCCESS; -} -#endif /* CONFIG_ACCEL_INTERRUPTS */ - - -static int read(const struct motion_sensor_t *s, intv3_t v) -{ - uint8_t data[6]; - int ret, status = 0; - - ret = raw_read8(s->port, s->i2c_spi_addr_flags, - BMI160_STATUS, &status); - if (ret != EC_SUCCESS) - return ret; - - /* - * If sensor data is not ready, return the previous read data. - * Note: return success so that motion senor task can read again - * to get the latest updated sensor data quickly. - */ - if (!(status & BMI160_DRDY_MASK(s->type))) { - if (v != s->raw_xyz) - memcpy(v, s->raw_xyz, sizeof(s->raw_xyz)); - return EC_SUCCESS; - } - - /* Read 6 bytes starting at xyz_reg */ - ret = raw_read_n(s->port, s->i2c_spi_addr_flags, - get_xyz_reg(s->type), data, 6); - - if (ret != EC_SUCCESS) { - CPRINTS("%s: type:0x%X RD XYZ Error %d", s->name, s->type, ret); - return ret; - } - normalize(s, v, data); - return EC_SUCCESS; -} - -static int init(const struct motion_sensor_t *s) -{ - int ret = 0, tmp, i; - struct accelgyro_saved_data_t *saved_data = BMI160_GET_SAVED_DATA(s); - - ret = raw_read8(s->port, s->i2c_spi_addr_flags, - BMI160_CHIP_ID, &tmp); - if (ret) - return EC_ERROR_UNKNOWN; - - if (tmp != BMI160_CHIP_ID_MAJOR && tmp != BMI168_CHIP_ID_MAJOR) { - /* The device may be lock on paging mode. Try to unlock it. */ - raw_write8(s->port, s->i2c_spi_addr_flags, - BMI160_CMD_REG, BMI160_CMD_EXT_MODE_EN_B0); - raw_write8(s->port, s->i2c_spi_addr_flags, - BMI160_CMD_REG, BMI160_CMD_EXT_MODE_EN_B1); - raw_write8(s->port, s->i2c_spi_addr_flags, - BMI160_CMD_REG, BMI160_CMD_EXT_MODE_EN_B2); - raw_write8(s->port, s->i2c_spi_addr_flags, - BMI160_CMD_EXT_MODE_ADDR, BMI160_CMD_PAGING_EN); - raw_write8(s->port, s->i2c_spi_addr_flags, - BMI160_CMD_EXT_MODE_ADDR, 0); - return EC_ERROR_ACCESS_DENIED; - } - - - if (s->type == MOTIONSENSE_TYPE_ACCEL) { - struct bmi160_drv_data_t *data = BMI160_GET_DATA(s); - - /* Reset the chip to be in a good state */ - raw_write8(s->port, s->i2c_spi_addr_flags, - BMI160_CMD_REG, BMI160_CMD_SOFT_RESET); - msleep(1); - data->flags &= ~(BMI160_FLAG_SEC_I2C_ENABLED | - (BMI160_FIFO_ALL_MASK << - BMI160_FIFO_FLAG_OFFSET)); -#ifdef CONFIG_GESTURE_HOST_DETECTION - data->enabled_activities = 0; - data->disabled_activities = 0; -#ifdef CONFIG_GESTURE_SIGMO - data->disabled_activities |= - 1 << MOTIONSENSE_ACTIVITY_SIG_MOTION; -#endif -#ifdef CONFIG_GESTURE_SENSOR_DOUBLE_TAP - data->disabled_activities |= - 1 << MOTIONSENSE_ACTIVITY_DOUBLE_TAP; -#endif -#endif - /* To avoid gyro wakeup */ - raw_write8(s->port, s->i2c_spi_addr_flags, - BMI160_PMU_TRIGGER, 0); - } - -#ifdef CONFIG_BMI160_SEC_I2C - if (s->type == MOTIONSENSE_TYPE_MAG) { - struct bmi160_drv_data_t *data = BMI160_GET_DATA(s); - - /* - * To be able to configure the real magnetometer, we must set - * the BMI160 magnetometer part (a pass through) in normal mode. - */ - raw_write8(s->port, s->i2c_spi_addr_flags, - BMI160_CMD_REG, BMI160_CMD_MODE_NORMAL(s->type)); - msleep(wakeup_time[s->type]); - - if ((data->flags & BMI160_FLAG_SEC_I2C_ENABLED) == 0) { - int ext_page_reg, pullup_reg; - /* Enable secondary interface */ - /* - * This is not part of the normal configuration but from - * code on Bosh github repo: - * https://github.com/BoschSensortec/BMI160_driver - * - * Magic command sequences - */ - raw_write8(s->port, s->i2c_spi_addr_flags, - BMI160_CMD_REG, BMI160_CMD_EXT_MODE_EN_B0); - raw_write8(s->port, s->i2c_spi_addr_flags, - BMI160_CMD_REG, BMI160_CMD_EXT_MODE_EN_B1); - raw_write8(s->port, s->i2c_spi_addr_flags, - BMI160_CMD_REG, BMI160_CMD_EXT_MODE_EN_B2); - - /* - * Change the register page to target mode, to change - * the internal pull ups of the secondary interface. - */ - raw_read8(s->port, s->i2c_spi_addr_flags, - BMI160_CMD_EXT_MODE_ADDR, &ext_page_reg); - raw_write8(s->port, s->i2c_spi_addr_flags, - BMI160_CMD_EXT_MODE_ADDR, - ext_page_reg | BMI160_CMD_TARGET_PAGE); - raw_read8(s->port, s->i2c_spi_addr_flags, - BMI160_CMD_EXT_MODE_ADDR, &ext_page_reg); - raw_write8(s->port, s->i2c_spi_addr_flags, - BMI160_CMD_EXT_MODE_ADDR, - ext_page_reg | BMI160_CMD_PAGING_EN); - raw_read8(s->port, s->i2c_spi_addr_flags, - BMI160_COM_C_TRIM_ADDR, &pullup_reg); - raw_write8(s->port, s->i2c_spi_addr_flags, - BMI160_COM_C_TRIM_ADDR, - pullup_reg | BMI160_COM_C_TRIM); - raw_read8(s->port, s->i2c_spi_addr_flags, - BMI160_CMD_EXT_MODE_ADDR, &ext_page_reg); - raw_write8(s->port, s->i2c_spi_addr_flags, - BMI160_CMD_EXT_MODE_ADDR, - ext_page_reg & ~BMI160_CMD_TARGET_PAGE); - raw_read8(s->port, s->i2c_spi_addr_flags, - BMI160_CMD_EXT_MODE_ADDR, &ext_page_reg); - - /* Set the i2c address of the compass */ - ret = raw_write8(s->port, s->i2c_spi_addr_flags, - BMI160_MAG_IF_0, - I2C_GET_ADDR( - CONFIG_ACCELGYRO_SEC_ADDR_FLAGS) - << 1); - - /* Enable the secondary interface as I2C */ - ret = raw_write8(s->port, s->i2c_spi_addr_flags, - BMI160_IF_CONF, - BMI160_IF_MODE_AUTO_I2C << - BMI160_IF_MODE_OFF); - data->flags |= BMI160_FLAG_SEC_I2C_ENABLED; - } - - - bmi160_sec_access_ctrl(s->port, s->i2c_spi_addr_flags, 1); - - ret = bmm150_init(s); - if (ret) - /* Leave the compass open for tinkering. */ - return ret; - - /* Leave the address for reading the data */ - raw_write8(s->port, s->i2c_spi_addr_flags, - BMI160_MAG_I2C_READ_ADDR, BMM150_BASE_DATA); - /* - * Put back the secondary interface in normal mode. - * BMI160 will poll based on the configure ODR. - */ - bmi160_sec_access_ctrl(s->port, s->i2c_spi_addr_flags, 0); - - /* - * Clean interrupt event that may have occurred while the - * BMI160 was in management mode. - */ - task_set_event(TASK_ID_MOTIONSENSE, - CONFIG_ACCELGYRO_BMI160_INT_EVENT, 0); - } -#endif - - for (i = X; i <= Z; i++) - saved_data->scale[i] = MOTION_SENSE_DEFAULT_SCALE; - /* - * The sensor is in Suspend mode at init, - * so set data rate to 0. - */ - saved_data->odr = 0; - set_range(s, s->default_range, 0); - - if (s->type == MOTIONSENSE_TYPE_ACCEL) { -#ifdef CONFIG_ACCEL_INTERRUPTS - ret = config_interrupt(s); -#endif - } - - return sensor_init_done(s); -} - -const struct accelgyro_drv bmi160_drv = { - .init = init, - .read = read, - .set_range = set_range, - .get_range = get_range, - .get_resolution = get_resolution, - .set_data_rate = set_data_rate, - .get_data_rate = get_data_rate, - .set_offset = set_offset, - .get_scale = get_scale, - .set_scale = set_scale, - .get_offset = get_offset, - .perform_calib = perform_calib, -#ifdef CONFIG_ACCEL_INTERRUPTS - .irq_handler = irq_handler, -#endif -#ifdef CONFIG_GESTURE_HOST_DETECTION - .manage_activity = manage_activity, - .list_activities = list_activities, -#endif -}; - -#ifdef CONFIG_CMD_I2C_STRESS_TEST_ACCEL -struct i2c_stress_test_dev bmi160_i2c_stress_test_dev = { - .reg_info = { - .read_reg = BMI160_CHIP_ID, - .read_val = BMI160_CHIP_ID_MAJOR, - .write_reg = BMI160_PMU_TRIGGER, - }, - .i2c_read = &raw_read8, - .i2c_write = &raw_write8, -}; -#endif /* CONFIG_CMD_I2C_STRESS_TEST_ACCEL */ - -int bmi160_get_sensor_temp(int idx, int *temp_ptr) -{ - struct motion_sensor_t *s = &motion_sensors[idx]; - int16_t temp; - int ret; - - ret = raw_read_n(s->port, s->i2c_spi_addr_flags, - BMI160_TEMPERATURE_0, - (uint8_t *)&temp, sizeof(temp)); - - if (ret || temp == BMI160_INVALID_TEMP) - return EC_ERROR_NOT_POWERED; - - *temp_ptr = C_TO_K(23 + ((temp + 256) >> 9)); - return 0; -} diff --git a/driver/accelgyro_bmi160.h b/driver/accelgyro_bmi160.h deleted file mode 100644 index a5a152f471..0000000000 --- a/driver/accelgyro_bmi160.h +++ /dev/null @@ -1,497 +0,0 @@ -/* 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. - */ - -/* BMI160 accelerometer and gyro and BMM150 compass module for Chrome EC */ - -#ifndef __CROS_EC_ACCELGYRO_BMI160_H -#define __CROS_EC_ACCELGYRO_BMI160_H - -#include "accelgyro.h" -#include "mag_bmm150.h" - -/* - * The addr field of motion_sensor support both SPI and I2C: - * This is defined in include/i2c.h and is no longer an 8bit - * address. The 7/10 bit address starts at bit 0 and leaves - * room for a 10 bit address, although we don't currently - * have any 10 bit slaves. I2C or SPI is indicated by a - * more significant bit - */ - -/* I2C addresses */ -#define BMI160_ADDR0_FLAGS 0x68 -#define BMI160_ADDR1_FLAGS 0x69 - -#define BMI160_CHIP_ID 0x00 -#define BMI160_CHIP_ID_MAJOR 0xd1 -#define BMI168_CHIP_ID_MAJOR 0xd2 - -#define BMI160_SPEC_ACC_STARTUP_TIME_MS 10 -#define BMI160_SPEC_GYR_STARTUP_TIME_MS 80 -#define BMI160_SPEC_MAG_STARTUP_TIME_MS 60 - - -#define BMI160_ERR_REG 0x02 -#define BMI160_PMU_STATUS 0x03 -#define BMI160_PMU_MAG_OFFSET 0 -#define BMI160_PMU_GYR_OFFSET 2 -#define BMI160_PMU_ACC_OFFSET 4 -#define BMI160_PMU_SENSOR_STATUS(_sensor_type, _val) \ - (((_val) >> (4 - 2 * (_sensor_type))) & 0x3) -#define BMI160_PMU_SUSPEND 0 -#define BMI160_PMU_NORMAL 1 -#define BMI160_PMU_LOW_POWER 2 -#define BMI160_PMU_FAST_STARTUP 3 - -#define BMI160_MAG_X_L_G 0x04 -#define BMI160_MAG_X_H_G 0x05 -#define BMI160_MAG_Y_L_G 0x06 -#define BMI160_MAG_Y_H_G 0x07 -#define BMI160_MAG_Z_L_G 0x08 -#define BMI160_MAG_Z_H_G 0x09 -#define BMI160_RHALL_L_G 0x0a -#define BMI160_RHALL_H_G 0x0b -#define BMI160_GYR_X_L_G 0x0c -#define BMI160_GYR_X_H_G 0x0d -#define BMI160_GYR_Y_L_G 0x0e -#define BMI160_GYR_Y_H_G 0x0f -#define BMI160_GYR_Z_L_G 0x10 -#define BMI160_GYR_Z_H_G 0x11 -#define BMI160_ACC_X_L_G 0x12 -#define BMI160_ACC_X_H_G 0x13 -#define BMI160_ACC_Y_L_G 0x14 -#define BMI160_ACC_Y_H_G 0x15 -#define BMI160_ACC_Z_L_G 0x16 -#define BMI160_ACC_Z_H_G 0x17 - -#define BMI160_SENSORTIME_0 0x18 -#define BMI160_SENSORTIME_1 0x19 -#define BMI160_SENSORTIME_2 0x1a - -#define BMI160_STATUS 0x1b -#define BMI160_POR_DETECTED BIT(0) -#define BMI160_GYR_SLF_TST BIT(1) -#define BMI160_MAG_MAN_OP BIT(2) -#define BMI160_FOC_RDY BIT(3) -#define BMI160_NVM_RDY BIT(4) -#define BMI160_DRDY_MAG BIT(5) -#define BMI160_DRDY_GYR BIT(6) -#define BMI160_DRDY_ACC BIT(7) -#define BMI160_DRDY_OFF(_sensor) (7 - (_sensor)) -#define BMI160_DRDY_MASK(_sensor) (1 << BMI160_DRDY_OFF(_sensor)) - -/* first 2 bytes are the interrupt reasons, next 2 some qualifier */ -#define BMI160_INT_STATUS_0 0x1c -#define BMI160_STEP_INT BIT(0) -#define BMI160_SIGMOT_INT BIT(1) -#define BMI160_ANYM_INT BIT(2) -#define BMI160_PMU_TRIGGER_INT BIT(3) -#define BMI160_D_TAP_INT BIT(4) -#define BMI160_S_TAP_INT BIT(5) -#define BMI160_ORIENT_INT BIT(6) -#define BMI160_FLAT_INT BIT(7) -#define BMI160_ORIENT_XY_MASK 0x30 -#define BMI160_ORIENT_PORTRAIT (0 << 4) -#define BMI160_ORIENT_PORTRAIT_INVERT BIT(4) -#define BMI160_ORIENT_LANDSCAPE (2 << 4) -#define BMI160_ORIENT_LANDSCAPE_INVERT (3 << 4) - - -#define BMI160_INT_STATUS_1 0x1d -#define BMI160_HIGHG_INT (1 << (2 + 8)) -#define BMI160_LOWG_INT (1 << (3 + 8)) -#define BMI160_DRDY_INT (1 << (4 + 8)) -#define BMI160_FFULL_INT (1 << (5 + 8)) -#define BMI160_FWM_INT (1 << (6 + 8)) -#define BMI160_NOMO_INT (1 << (7 + 8)) - -#define BMI160_INT_MASK 0xFFFF - -#define BMI160_INT_STATUS_2 0x1e -#define BMI160_INT_STATUS_3 0x1f -#define BMI160_FIRST_X (1 << (0 + 16)) -#define BMI160_FIRST_Y (1 << (1 + 16)) -#define BMI160_FIRST_Z (1 << (2 + 16)) -#define BMI160_SIGN (1 << (3 + 16)) -#define BMI160_ANYM_OFFSET 0 -#define BMI160_TAP_OFFSET 4 -#define BMI160_HIGH_OFFSET 8 -#define BMI160_INT_INFO(_type, _data) \ -(CONCAT2(BMI160_, _data) << CONCAT3(BMI160_, _type, _OFFSET)) - -#define BMI160_ORIENT_Z (1 << (6 + 24)) -#define BMI160_FLAT (1 << (7 + 24)) - -#define BMI160_TEMPERATURE_0 0x20 -#define BMI160_TEMPERATURE_1 0x21 -#define BMI160_INVALID_TEMP 0x8000 - - -#define BMI160_FIFO_LENGTH_0 0x22 -#define BMI160_FIFO_LENGTH_1 0x23 -#define BMI160_FIFO_LENGTH_MASK (BIT(11) - 1) -#define BMI160_FIFO_DATA 0x24 -enum fifo_header { - BMI160_EMPTY = 0x80, - BMI160_SKIP = 0x40, - BMI160_TIME = 0x44, - BMI160_CONFIG = 0x48 -}; - -#define BMI160_FH_MODE_MASK 0xc0 -#define BMI160_FH_PARM_OFFSET 2 -#define BMI160_FH_PARM_MASK (0x7 << BMI160_FH_PARM_OFFSET) -#define BMI160_FH_EXT_MASK 0x03 - - -#define BMI160_ACC_CONF 0x40 -#define BMI160_ODR_MASK 0x0F -#define BMI160_ACC_BW_OFFSET 4 -#define BMI160_ACC_BW_MASK (0x7 << BMI160_ACC_BW_OFFSET) - -#define BMI160_ACC_RANGE 0x41 -#define BMI160_GSEL_2G 0x03 -#define BMI160_GSEL_4G 0x05 -#define BMI160_GSEL_8G 0x08 -#define BMI160_GSEL_16G 0x0c - -#define BMI160_GYR_CONF 0x42 -#define BMI160_GYR_BW_OFFSET 4 -#define BMI160_GYR_BW_MASK (0x3 << BMI160_GYR_BW_OFFSET) - -#define BMI160_GYR_RANGE 0x43 -#define BMI160_DPS_SEL_2000 0x00 -#define BMI160_DPS_SEL_1000 0x01 -#define BMI160_DPS_SEL_500 0x02 -#define BMI160_DPS_SEL_250 0x03 -#define BMI160_DPS_SEL_125 0x04 - - -#define BMI160_MAG_CONF 0x44 - -/* odr = 100 / (1 << (8 - reg)) ,within limit */ -#define BMI160_ODR_0_78HZ 0x01 -#define BMI160_ODR_100HZ 0x08 - -#define BMI160_REG_TO_ODR(_regval) \ - ((_regval) < BMI160_ODR_100HZ ? 100000 / (1 << (8 - (_regval))) : \ - 100000 * (1 << ((_regval) - 8))) -#define BMI160_ODR_TO_REG(_odr) \ - ((_odr) < 100000 ? (__builtin_clz(100000 / (_odr)) - 24) : \ - (39 - __builtin_clz((_odr) / 100000))) - -#define BMI160_CONF_REG(_sensor) (0x40 + 2 * (_sensor)) -#define BMI160_RANGE_REG(_sensor) (0x41 + 2 * (_sensor)) - -#define BMI160_FIFO_DOWNS 0x45 -#define BMI160_FIFO_CONFIG_0 0x46 -#define BMI160_FIFO_CONFIG_1 0x47 -#define BMI160_FIFO_TAG_TIME_EN BIT(1) -#define BMI160_FIFO_TAG_INT2_EN BIT(2) -#define BMI160_FIFO_TAG_INT1_EN BIT(3) -#define BMI160_FIFO_HEADER_EN BIT(4) -#define BMI160_FIFO_MAG_EN BIT(5) -#define BMI160_FIFO_ACC_EN BIT(6) -#define BMI160_FIFO_GYR_EN BIT(7) -#define BMI160_FIFO_TARG_INT(_i) CONCAT3(BMI160_FIFO_TAG_INT, _i, _EN) -#define BMI160_FIFO_SENSOR_EN(_sensor) \ - ((_sensor) == MOTIONSENSE_TYPE_ACCEL ? BMI160_FIFO_ACC_EN : \ - ((_sensor) == MOTIONSENSE_TYPE_GYRO ? BMI160_FIFO_GYR_EN : \ - BMI160_FIFO_MAG_EN)) - -#define BMI160_MAG_IF_0 0x4b -#define BMI160_MAG_I2C_ADDRESS BMI160_MAG_IF_0 -#define BMI160_MAG_IF_1 0x4c -#define BMI160_MAG_I2C_CONTROL BMI160_MAG_IF_1 -#define BMI160_MAG_READ_BURST_MASK 3 -#define BMI160_MAG_READ_BURST_1 0 -#define BMI160_MAG_READ_BURST_2 1 -#define BMI160_MAG_READ_BURST_6 2 -#define BMI160_MAG_READ_BURST_8 3 -#define BMI160_MAG_OFFSET_OFF 3 -#define BMI160_MAG_OFFSET_MASK (0xf << BMI160_MAG_OFFSET_OFF) -#define BMI160_MAG_MANUAL_EN BIT(7) - -#define BMI160_MAG_IF_2 0x4d -#define BMI160_MAG_I2C_READ_ADDR BMI160_MAG_IF_2 -#define BMI160_MAG_IF_3 0x4e -#define BMI160_MAG_I2C_WRITE_ADDR BMI160_MAG_IF_3 -#define BMI160_MAG_IF_4 0x4f -#define BMI160_MAG_I2C_WRITE_DATA BMI160_MAG_IF_4 -#define BMI160_MAG_I2C_READ_DATA BMI160_MAG_X_L_G - -#define BMI160_INT_EN_0 0x50 -#define BMI160_INT_ANYMO_X_EN BIT(0) -#define BMI160_INT_ANYMO_Y_EN BIT(1) -#define BMI160_INT_ANYMO_Z_EN BIT(2) -#define BMI160_INT_D_TAP_EN BIT(4) -#define BMI160_INT_S_TAP_EN BIT(5) -#define BMI160_INT_ORIENT_EN BIT(6) -#define BMI160_INT_FLAT_EN BIT(7) -#define BMI160_INT_EN_1 0x51 -#define BMI160_INT_HIGHG_X_EN BIT(0) -#define BMI160_INT_HIGHG_Y_EN BIT(1) -#define BMI160_INT_HIGHG_Z_EN BIT(2) -#define BMI160_INT_LOW_EN BIT(3) -#define BMI160_INT_DRDY_EN BIT(4) -#define BMI160_INT_FFUL_EN BIT(5) -#define BMI160_INT_FWM_EN BIT(6) -#define BMI160_INT_EN_2 0x52 -#define BMI160_INT_NOMOX_EN BIT(0) -#define BMI160_INT_NOMOY_EN BIT(1) -#define BMI160_INT_NOMOZ_EN BIT(2) -#define BMI160_INT_STEP_DET_EN BIT(3) - -#define BMI160_INT_OUT_CTRL 0x53 -#define BMI160_INT_EDGE_CTRL BIT(0) -#define BMI160_INT_LVL_CTRL BIT(1) -#define BMI160_INT_OD BIT(2) -#define BMI160_INT_OUTPUT_EN BIT(3) -#define BMI160_INT1_CTRL_OFFSET 0 -#define BMI160_INT2_CTRL_OFFSET 4 -#define BMI160_INT_CTRL(_i, _bit) \ -(CONCAT2(BMI160_INT_, _bit) << CONCAT3(BMI160_INT, _i, _CTRL_OFFSET)) - -#define BMI160_INT_LATCH 0x54 -#define BMI160_INT1_INPUT_EN BIT(4) -#define BMI160_INT2_INPUT_EN BIT(5) -#define BMI160_LATCH_MASK 0xf -#define BMI160_LATCH_NONE 0 -#define BMI160_LATCH_5MS 5 -#define BMI160_LATCH_FOREVER 0xf - -#define BMI160_INT_MAP_0 0x55 -#define BMI160_INT_LOWG_STEP BIT(0) -#define BMI160_INT_HIGHG BIT(1) -#define BMI160_INT_ANYMOTION BIT(2) -#define BMI160_INT_NOMOTION BIT(3) -#define BMI160_INT_D_TAP BIT(4) -#define BMI160_INT_S_TAP BIT(5) -#define BMI160_INT_ORIENT BIT(6) -#define BMI160_INT_FLAT BIT(7) - -#define BMI160_INT_MAP_1 0x56 -#define BMI160_INT_PMU_TRIG BIT(0) -#define BMI160_INT_FFULL BIT(1) -#define BMI160_INT_FWM BIT(2) -#define BMI160_INT_DRDY BIT(3) -#define BMI160_INT1_MAP_OFFSET 4 -#define BMI160_INT2_MAP_OFFSET 0 -#define BMI160_INT_MAP(_i, _bit) \ -(CONCAT2(BMI160_INT_, _bit) << CONCAT3(BMI160_INT, _i, _MAP_OFFSET)) -#define BMI160_INT_FIFO_MAP BMI160_INT_MAP_1 - -#define BMI160_INT_MAP_2 0x57 - -#define BMI160_INT_MAP_INT_1 BMI160_INT_MAP_0 -#define BMI160_INT_MAP_INT_2 BMI160_INT_MAP_2 -#define BMI160_INT_MAP_REG(_i) CONCAT2(BMI160_INT_MAP_INT_, _i) - -#define BMI160_INT_DATA_0 0x58 -#define BMI160_INT_DATA_1 0x59 - -#define BMI160_INT_MOTION_0 0x5f -#define BMI160_INT_MOTION_1 0x60 -/* - * The formula is defined in 2.11.25 (any motion interrupt [1]). - * - * if we want threshold at a (in mg), the register should be x, where - * x * 7.81mg = a, assuming a range of 4G, which is - * x * 4 * 1.953 = a so - * x = a * 1000 / range * 1953 - */ -#define BMI160_MOTION_TH(_s, _mg) \ - (MIN(((_mg) * 1000) / ((_s)->drv->get_range(_s) * 1953), 0xff)) -#define BMI160_INT_MOTION_2 0x61 -#define BMI160_INT_MOTION_3 0x62 -#define BMI160_MOTION_NO_MOT_SEL BIT(0) -#define BMI160_MOTION_SIG_MOT_SEL BIT(1) -#define BMI160_MOTION_SKIP_OFF 2 -#define BMI160_MOTION_SKIP_MASK 0x3 -#define BMI160_MOTION_SKIP_TIME(_ms) \ - (MIN(__fls((_ms) / 1500), BMI160_MOTION_SKIP_MASK)) -#define BMI160_MOTION_PROOF_OFF 4 -#define BMI160_MOTION_PROOF_MASK 0x3 -#define BMI160_MOTION_PROOF_TIME(_ms) \ - (MIN(__fls((_ms) / 250), BMI160_MOTION_PROOF_MASK)) - -#define BMI160_INT_TAP_0 0x63 -#define BMI160_TAP_DUR(_s, _ms) \ - ((_ms) <= 250 ? MAX((_ms), 50) / 50 - 1 : \ - (_ms) <= 500 ? 4 + ((_ms) - 250) / 125 : \ - (_ms) < 700 ? 6 : 7) - -#define BMI160_INT_TAP_1 0x64 -#define BMI160_TAP_TH(_s, _mg) \ - (MIN(((_mg) * 1000) / ((_s)->drv->get_range(_s) * 31250), 0x1f)) - -#define BMI160_INT_ORIENT_0 0x65 - -/* No hysterisis, theta block, int on slope > 0.2 or axis > 1.5, symmetrical */ -#define BMI160_INT_ORIENT_0_INIT_VAL 0x48 - -#define BMI160_INT_ORIENT_1 0x66 - -/* no axes remap, no int on up/down, no blocking angle */ -#define BMI160_INT_ORIENT_1_INIT_VAL 0x00 - -#define BMI160_INT_FLAT_0 0x67 -#define BMI160_INT_FLAT_1 0x68 - -#define BMI160_FOC_CONF 0x69 -#define BMI160_FOC_GYRO_EN BIT(6) -#define BMI160_FOC_ACC_PLUS_1G 1 -#define BMI160_FOC_ACC_MINUS_1G 2 -#define BMI160_FOC_ACC_0G 3 -#define BMI160_FOC_ACC_Z_OFFSET 0 -#define BMI160_FOC_ACC_Y_OFFSET 2 -#define BMI160_FOC_ACC_X_OFFSET 4 - -#define BMI160_CONF 0x6a -#define BMI160_IF_CONF 0x6b -#define BMI160_IF_MODE_OFF 4 -#define BMI160_IF_MODE_MASK 3 -#define BMI160_IF_MODE_AUTO_OFF 0 -#define BMI160_IF_MODE_I2C_IOS 1 -#define BMI160_IF_MODE_AUTO_I2C 2 - -#define BMI160_PMU_TRIGGER 0x6c -#define BMI160_SELF_TEST 0x6d - -#define BMI160_OFFSET_ACC70 0x71 -#define BMI160_OFFSET_ACC_MULTI_MG (3900 * 1024) -#define BMI160_OFFSET_ACC_DIV_MG 1000000 -#define BMI160_OFFSET_GYR70 0x74 -#define BMI160_OFFSET_GYRO_MULTI_MDS (61 * 1024) -#define BMI160_OFFSET_GYRO_DIV_MDS 1000 -#define BMI160_OFFSET_EN_GYR98 0x77 -#define BMI160_OFFSET_ACC_EN BIT(6) -#define BMI160_OFFSET_GYRO_EN BIT(7) - - -#define BMI160_CMD_REG 0x7e -#define BMI160_CMD_SOFT_RESET 0xb6 -#define BMI160_CMD_NOOP 0x00 -#define BMI160_CMD_START_FOC 0x03 -#define BMI160_CMD_ACC_MODE_OFFSET 0x10 -#define BMI160_CMD_ACC_MODE_SUSP 0x10 -#define BMI160_CMD_ACC_MODE_NORMAL 0x11 -#define BMI160_CMD_ACC_MODE_LOWPOWER 0x12 -#define BMI160_CMD_GYR_MODE_SUSP 0x14 -#define BMI160_CMD_GYR_MODE_NORMAL 0x15 -#define BMI160_CMD_GYR_MODE_FAST_STARTUP 0x17 -#define BMI160_CMD_MAG_MODE_SUSP 0x18 -#define BMI160_CMD_MAG_MODE_NORMAL 0x19 -#define BMI160_CMD_MAG_MODE_LOWPOWER 0x1a -#define BMI160_CMD_MODE_SUSPEND(_sensor_type) \ - (BMI160_CMD_ACC_MODE_OFFSET | (_sensor_type) << 2 | BMI160_PMU_SUSPEND) -#define BMI160_CMD_MODE_NORMAL(_sensor_type) \ - (BMI160_CMD_ACC_MODE_OFFSET | (_sensor_type) << 2 | BMI160_PMU_NORMAL) - -#define BMI160_CMD_FIFO_FLUSH 0xb0 -#define BMI160_CMD_INT_RESET 0xb1 -#define BMI160_CMD_SOFT_RESET 0xb6 -#define BMI160_CMD_EXT_MODE_EN_B0 0x37 -#define BMI160_CMD_EXT_MODE_EN_B1 0x9a -#define BMI160_CMD_EXT_MODE_EN_B2 0xc0 - -#define BMI160_CMD_EXT_MODE_ADDR 0x7f -#define BMI160_CMD_PAGING_EN BIT(7) -#define BMI160_CMD_TARGET_PAGE BIT(4) -#define BMI160_COM_C_TRIM_ADDR 0x85 -#define BMI160_COM_C_TRIM (3 << 4) - - - -#define BMI160_CMD_TGT_PAGE 0 -#define BMI160_CMD_TGT_PAGE_COM 1 -#define BMI160_CMD_TGT_PAGE_ACC 2 -#define BMI160_CMD_TGT_PAGE_GYR 3 - -#define BMI160_FF_FRAME_LEN_TS 4 -#define BMI160_FF_DATA_LEN_ACC 6 -#define BMI160_FF_DATA_LEN_GYR 6 -#define BMI160_FF_DATA_LEN_MAG 8 - -/* Sensor resolution in number of bits. This sensor has fixed resolution. */ -#define BMI160_RESOLUTION 16 - -/* Min and Max sampling frequency in mHz */ -#define BMI160_ACCEL_MIN_FREQ 12500 -#define BMI160_ACCEL_MAX_FREQ MOTION_MAX_SENSOR_FREQUENCY(1600000, 100000) -#define BMI160_GYRO_MIN_FREQ 25000 -#define BMI160_GYRO_MAX_FREQ MOTION_MAX_SENSOR_FREQUENCY(3200000, 100000) - -extern const struct accelgyro_drv bmi160_drv; - -enum bmi160_running_mode { - STANDARD_UI_9DOF_FIFO = 0, - STANDARD_UI_IMU_FIFO = 1, - STANDARD_UI_IMU = 2, - STANDARD_UI_ADVANCEPOWERSAVE = 3, - ACCEL_PEDOMETER = 4, - APPLICATION_HEAD_TRACKING = 5, - APPLICATION_NAVIGATION = 6, - APPLICATION_REMOTE_CONTROL = 7, - APPLICATION_INDOOR_NAVIGATION = 8, -}; - -#define BMI160_FLAG_SEC_I2C_ENABLED BIT(0) -#define BMI160_FIFO_FLAG_OFFSET 4 -#define BMI160_FIFO_ALL_MASK 7 - -struct bmi160_drv_data_t { - struct accelgyro_saved_data_t saved_data[3]; - uint8_t flags; - uint8_t enabled_activities; - uint8_t disabled_activities; -#ifdef CONFIG_MAG_BMI160_BMM150 - struct bmm150_private_data compass; -#endif -#ifdef CONFIG_BMI160_ORIENTATION_SENSOR - uint8_t raw_orientation; - enum motionsensor_orientation orientation; - enum motionsensor_orientation last_orientation; -#endif - -}; - -#define BMI160_GET_DATA(_s) \ - ((struct bmi160_drv_data_t *)(_s)->drv_data) -#define BMI160_GET_SAVED_DATA(_s) \ - (&BMI160_GET_DATA(_s)->saved_data[(_s)->type]) - -#ifdef CONFIG_BMI160_ORIENTATION_SENSOR -#define ORIENTATION_CHANGED(_sensor) \ - (BMI160_GET_DATA(_sensor)->orientation != \ - BMI160_GET_DATA(_sensor)->last_orientation) - -#define GET_ORIENTATION(_sensor) \ - (BMI160_GET_DATA(_sensor)->orientation) - -#define SET_ORIENTATION(_sensor, _val) \ - (BMI160_GET_DATA(_sensor)->orientation = _val) - -#define SET_ORIENTATION_UPDATED(_sensor) \ - (BMI160_GET_DATA(_sensor)->last_orientation = \ - BMI160_GET_DATA(_sensor)->orientation) -#endif - -void bmi160_interrupt(enum gpio_signal signal); - -#ifdef CONFIG_BMI160_SEC_I2C -/* Functions to access the secondary device through the accel/gyro. */ -int bmi160_sec_raw_read8(const int port, const uint16_t addr_flags, - const uint8_t reg, int *data_ptr); -int bmi160_sec_raw_write8(const int port, const uint16_t addr_flags, - const uint8_t reg, int data); -#endif - -#ifdef CONFIG_CMD_I2C_STRESS_TEST_ACCEL -extern struct i2c_stress_test_dev bmi160_i2c_stress_test_dev; -#endif - -int bmi160_get_sensor_temp(int idx, int *temp_ptr); -#endif /* __CROS_EC_ACCELGYRO_BMI160_H */ diff --git a/driver/accelgyro_lsm6ds0.c b/driver/accelgyro_lsm6ds0.c deleted file mode 100644 index 54ee1c77cc..0000000000 --- a/driver/accelgyro_lsm6ds0.c +++ /dev/null @@ -1,435 +0,0 @@ -/* Copyright 2014 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. - */ - -/** - * LSM6DS0 accelerometer and gyro module for Chrome EC - * 3D digital accelerometer & 3D digital gyroscope - */ - -#include "accelgyro.h" -#include "common.h" -#include "console.h" -#include "driver/accelgyro_lsm6ds0.h" -#include "hooks.h" -#include "i2c.h" -#include "math_util.h" -#include "task.h" -#include "util.h" - -#define CPUTS(outstr) cputs(CC_ACCEL, outstr) -#define CPRINTS(format, args...) cprints(CC_ACCEL, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_ACCEL, format, ## args) - -/* - * Struct for pairing an engineering value with the register value for a - * parameter. - */ -struct accel_param_pair { - int val; /* Value in engineering units. */ - int reg_val; /* Corresponding register value. */ -}; - -/* List of range values in +/-G's and their associated register values. */ -static const struct accel_param_pair g_ranges[] = { - {2, LSM6DS0_GSEL_2G}, - {4, LSM6DS0_GSEL_4G}, - {8, LSM6DS0_GSEL_8G} -}; - -/* - * List of angular rate range values in +/-dps's - * and their associated register values. - */ -const struct accel_param_pair dps_ranges[] = { - {245, LSM6DS0_DPS_SEL_245}, - {500, LSM6DS0_DPS_SEL_500}, - {1000, LSM6DS0_DPS_SEL_1000}, - {2000, LSM6DS0_DPS_SEL_2000} -}; - -static inline const struct accel_param_pair *get_range_table( - enum motionsensor_type type, int *psize) -{ - if (MOTIONSENSE_TYPE_ACCEL == type) { - if (psize) - *psize = ARRAY_SIZE(g_ranges); - return g_ranges; - } else { - if (psize) - *psize = ARRAY_SIZE(dps_ranges); - return dps_ranges; - } -} - -/* List of ODR (gyro off) values in mHz and their associated register values.*/ -const struct accel_param_pair gyro_on_odr[] = { - {0, LSM6DS0_ODR_PD}, - {15000, LSM6DS0_ODR_15HZ}, - {59000, LSM6DS0_ODR_59HZ}, - {119000, LSM6DS0_ODR_119HZ}, - {238000, LSM6DS0_ODR_238HZ}, - {476000, LSM6DS0_ODR_476HZ}, - {952000, LSM6DS0_ODR_952HZ} -}; - -/* List of ODR (gyro on) values in mHz and their associated register values. */ -const struct accel_param_pair gyro_off_odr[] = { - {0, LSM6DS0_ODR_PD}, - {10000, LSM6DS0_ODR_10HZ}, - {50000, LSM6DS0_ODR_50HZ}, - {119000, LSM6DS0_ODR_119HZ}, - {238000, LSM6DS0_ODR_238HZ}, - {476000, LSM6DS0_ODR_476HZ}, - {952000, LSM6DS0_ODR_952HZ} -}; - -static inline const struct accel_param_pair *get_odr_table( - enum motionsensor_type type, int *psize) -{ - if (MOTIONSENSE_TYPE_ACCEL == type) { - if (psize) - *psize = ARRAY_SIZE(gyro_off_odr); - return gyro_off_odr; - } else { - if (psize) - *psize = ARRAY_SIZE(gyro_on_odr); - return gyro_on_odr; - } -} - -static inline int get_ctrl_reg(enum motionsensor_type type) -{ - return (MOTIONSENSE_TYPE_ACCEL == type) ? - LSM6DS0_CTRL_REG6_XL : LSM6DS0_CTRL_REG1_G; -} - -static inline int get_xyz_reg(enum motionsensor_type type) -{ - return (MOTIONSENSE_TYPE_ACCEL == type) ? - LSM6DS0_OUT_X_L_XL : LSM6DS0_OUT_X_L_G; -} - -/** - * @return reg value that matches the given engineering value passed in. - * The round_up flag is used to specify whether to round up or down. - * Note, this function always returns a valid reg value. If the request is - * outside the range of values, it returns the closest valid reg value. - */ -static int get_reg_val(const int eng_val, const int round_up, - const struct accel_param_pair *pairs, const int size) -{ - int i; - for (i = 0; i < size - 1; i++) { - if (eng_val <= pairs[i].val) - break; - - if (eng_val < pairs[i+1].val) { - if (round_up) - i += 1; - break; - } - } - return pairs[i].reg_val; -} - -/** - * @return engineering value that matches the given reg val - */ -static int get_engineering_val(const int reg_val, - const struct accel_param_pair *pairs, const int size) -{ - int i; - for (i = 0; i < size; i++) { - if (reg_val == pairs[i].reg_val) - break; - } - return pairs[i].val; -} - -/** - * Read register from accelerometer. - */ -static inline int raw_read8(const int port, const uint16_t i2c_addr_flags, - const int reg, int *data_ptr) -{ - return i2c_read8(port, i2c_addr_flags, reg, data_ptr); -} - -/** - * Write register from accelerometer. - */ -static inline int raw_write8(const int port, const uint16_t i2c_addr_flags, - const int reg, int data) -{ - return i2c_write8(port, i2c_addr_flags, reg, data); -} - -static int set_range(const struct motion_sensor_t *s, - int range, - int rnd) -{ - int ret, ctrl_val, range_tbl_size; - uint8_t ctrl_reg, reg_val; - const struct accel_param_pair *ranges; - struct lsm6ds0_data *data = s->drv_data; - - ctrl_reg = get_ctrl_reg(s->type); - ranges = get_range_table(s->type, &range_tbl_size); - - reg_val = get_reg_val(range, rnd, ranges, range_tbl_size); - - /* - * Lock accel resource to prevent another task from attempting - * to write accel parameters until we are done. - */ - mutex_lock(s->mutex); - - ret = raw_read8(s->port, s->i2c_spi_addr_flags, - ctrl_reg, &ctrl_val); - if (ret != EC_SUCCESS) - goto accel_cleanup; - - ctrl_val = (ctrl_val & ~LSM6DS0_RANGE_MASK) | reg_val; - ret = raw_write8(s->port, s->i2c_spi_addr_flags, - ctrl_reg, ctrl_val); - - /* Now that we have set the range, update the driver's value. */ - if (ret == EC_SUCCESS) - data->base.range = get_engineering_val(reg_val, ranges, - range_tbl_size); - -accel_cleanup: - mutex_unlock(s->mutex); - return ret; -} - -static int get_range(const struct motion_sensor_t *s) -{ - struct lsm6ds0_data *data = s->drv_data; - - return data->base.range; -} - -static int get_resolution(const struct motion_sensor_t *s) -{ - return LSM6DS0_RESOLUTION; -} - -static int set_data_rate(const struct motion_sensor_t *s, - int rate, - int rnd) -{ - int ret, val, odr_tbl_size; - uint8_t ctrl_reg, reg_val; - const struct accel_param_pair *data_rates; - struct lsm6ds0_data *data = s->drv_data; - - ctrl_reg = get_ctrl_reg(s->type); - data_rates = get_odr_table(s->type, &odr_tbl_size); - reg_val = get_reg_val(rate, rnd, data_rates, odr_tbl_size); - - /* - * Lock accel resource to prevent another task from attempting - * to write accel parameters until we are done. - */ - mutex_lock(s->mutex); - - ret = raw_read8(s->port, s->i2c_spi_addr_flags, ctrl_reg, &val); - if (ret != EC_SUCCESS) - goto accel_cleanup; - - val = (val & ~LSM6DS0_ODR_MASK) | reg_val; - ret = raw_write8(s->port, s->i2c_spi_addr_flags, ctrl_reg, val); - - /* Now that we have set the odr, update the driver's value. */ - if (ret == EC_SUCCESS) - data->base.odr = get_engineering_val(reg_val, data_rates, - odr_tbl_size); - - /* CTRL_REG3_G 12h - * [7] low-power mode = 0; - * [6] high pass filter disabled; - * [5:4] 0 keep const 0 - * [3:0] HPCF_G - * Table 48 Gyroscope high-pass filter cutoff frequency - */ - if (MOTIONSENSE_TYPE_GYRO == s->type) { - ret = raw_read8(s->port, s->i2c_spi_addr_flags, - LSM6DS0_CTRL_REG3_G, &val); - if (ret != EC_SUCCESS) - goto accel_cleanup; - val &= ~(0x3 << 4); /* clear bit [5:4] */ - val = (rate > 119000) ? - (val | (1<<7)) /* set high-power mode */ : - (val & ~(1<<7)); /* set low-power mode */ - ret = raw_write8(s->port, s->i2c_spi_addr_flags, - LSM6DS0_CTRL_REG3_G, val); - } - -accel_cleanup: - mutex_unlock(s->mutex); - return ret; -} - -static int get_data_rate(const struct motion_sensor_t *s) -{ - struct lsm6ds0_data *data = s->drv_data; - - return data->base.odr; -} - -static int set_offset(const struct motion_sensor_t *s, - const int16_t *offset, - int16_t temp) -{ - /* temperature is ignored */ - struct lsm6ds0_data *data = s->drv_data; - data->offset[X] = offset[X]; - data->offset[Y] = offset[Y]; - data->offset[Z] = offset[Z]; - return EC_SUCCESS; -} - -static int get_offset(const struct motion_sensor_t *s, - int16_t *offset, - int16_t *temp) -{ - struct lsm6ds0_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; -} - -static int is_data_ready(const struct motion_sensor_t *s, int *ready) -{ - int ret, tmp; - - ret = raw_read8(s->port, s->i2c_spi_addr_flags, - LSM6DS0_STATUS_REG, &tmp); - - if (ret != EC_SUCCESS) { - CPRINTS("%s type:0x%X RS Error", s->name, s->type); - return ret; - } - - if (MOTIONSENSE_TYPE_ACCEL == s->type) - *ready = (LSM6DS0_STS_XLDA_UP == (tmp & LSM6DS0_STS_XLDA_MASK)); - else - *ready = (LSM6DS0_STS_GDA_UP == (tmp & LSM6DS0_STS_GDA_MASK)); - - return EC_SUCCESS; -} - -static int read(const struct motion_sensor_t *s, intv3_t v) -{ - uint8_t raw[6]; - uint8_t xyz_reg; - int ret, range, i, tmp = 0; - struct lsm6ds0_data *data = s->drv_data; - - ret = is_data_ready(s, &tmp); - if (ret != EC_SUCCESS) - return ret; - - /* - * If sensor data is not ready, return the previous read data. - * Note: return success so that motion senor task can read again - * to get the latest updated sensor data quickly. - */ - if (!tmp) { - if (v != s->raw_xyz) - memcpy(v, s->raw_xyz, sizeof(s->raw_xyz)); - return EC_SUCCESS; - } - - xyz_reg = get_xyz_reg(s->type); - - /* Read 6 bytes starting at xyz_reg */ - ret = i2c_read_block(s->port, s->i2c_spi_addr_flags, - xyz_reg, raw, 6); - - if (ret != EC_SUCCESS) { - CPRINTS("%s type:0x%X RD XYZ Error", - s->name, s->type); - return ret; - } - - for (i = X; i <= Z; i++) - v[i] = (int16_t)((raw[i * 2 + 1] << 8) | raw[i * 2]); - - rotate(v, *s->rot_standard_ref, v); - - /* apply offset in the device coordinates */ - range = get_range(s); - for (i = X; i <= Z; i++) - v[i] += (data->offset[i] << 5) / range; - - return EC_SUCCESS; -} - -static int init(const struct motion_sensor_t *s) -{ - int ret = 0, tmp; - - ret = raw_read8(s->port, s->i2c_spi_addr_flags, - LSM6DS0_WHO_AM_I_REG, &tmp); - if (ret) - return EC_ERROR_UNKNOWN; - - if (tmp != LSM6DS0_WHO_AM_I) - return EC_ERROR_ACCESS_DENIED; - - /* - * This sensor can be powered through an EC reboot, so the state of - * the sensor is unknown here. Initiate software reset to restore - * sensor to default. - * [6] BDU Enable Block Data Update. - * [0] SW_RESET software reset - * - * lsm6ds0 supports both accel & gyro features - * Board will see two virtual sensor devices: accel & gyro. - * Requirement: Accel need be init before gyro. - * SW_RESET is down for accel only! - */ - if (MOTIONSENSE_TYPE_ACCEL == s->type) { - - mutex_lock(s->mutex); - ret = raw_read8(s->port, s->i2c_spi_addr_flags, - LSM6DS0_CTRL_REG8, &tmp); - if (ret) { - mutex_unlock(s->mutex); - return EC_ERROR_UNKNOWN; - } - tmp |= (1 | LSM6DS0_BDU_ENABLE); - ret = raw_write8(s->port, s->i2c_spi_addr_flags, - LSM6DS0_CTRL_REG8, tmp); - mutex_unlock(s->mutex); - - if (ret) - return ret; - - /* Power Down Gyro */ - ret = raw_write8(s->port, s->i2c_spi_addr_flags, - LSM6DS0_CTRL_REG1_G, 0x0); - if (ret) - return ret; - } - return sensor_init_done(s); -} - -const struct accelgyro_drv lsm6ds0_drv = { - .init = init, - .read = read, - .set_range = set_range, - .get_range = get_range, - .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, -}; diff --git a/driver/accelgyro_lsm6ds0.h b/driver/accelgyro_lsm6ds0.h deleted file mode 100644 index c6b0789c08..0000000000 --- a/driver/accelgyro_lsm6ds0.h +++ /dev/null @@ -1,133 +0,0 @@ -/* Copyright 2014 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. - */ - -/* LSM6DS0 accelerometer and gyro module for Chrome EC */ - -#ifndef __CROS_EC_ACCELGYRO_LSM6DS0_H -#define __CROS_EC_ACCELGYRO_LSM6DS0_H - -#include "accelgyro.h" -#include "task.h" - -/* - * 7-bit address is 110101Xb. Where 'X' is determined - * by the voltage on the ADDR pin. - */ -#define LSM6DS0_ADDR0_FLAGS 0x6a -#define LSM6DS0_ADDR1_FLAGS 0x6b - -/* who am I */ -#define LSM6DS0_WHO_AM_I 0x68 - -/* Chip specific registers. */ -#define LSM6DS0_ACT_THS 0x04 -#define LSM6DS0_ACT_DUR 0x05 -#define LSM6DS0_INT_GEN_CFG_XL 0x06 -#define LSM6DS0_INT_GEN_THS_X_XL 0x07 -#define LSM6DS0_INT_GEN_THS_Y_XL 0x08 -#define LSM6DS0_INT_GEN_THS_Z_XL 0x09 -#define LSM6DS0_INT_GEN_DUR_XL 0x0a -#define LSM6DS0_REFERENCE_G 0x0b -#define LSM6DS0_INT_CTRL 0x0c -#define LSM6DS0_WHO_AM_I_REG 0x0f -#define LSM6DS0_CTRL_REG1_G 0x10 -#define LSM6DS0_CTRL_REG2_G 0x11 -#define LSM6DS0_CTRL_REG3_G 0x12 -#define LSM6DS0_ORIENT_CFG_G 0x13 -#define LSM6DS0_INT_GEN_SRC_G 0x14 -#define LSM6DS0_OUT_TEMP_L 0x15 -#define LSM6DS0_OUT_TEMP_H 0x16 -#define LSM6DS0_OUT_X_L_G 0x18 -#define LSM6DS0_OUT_X_H_G 0x19 -#define LSM6DS0_OUT_Y_L_G 0x1a -#define LSM6DS0_OUT_Y_H_G 0x1b -#define LSM6DS0_OUT_Z_L_G 0x1c -#define LSM6DS0_OUT_Z_H_G 0x1d -#define LSM6DS0_CTRL_REG4 0x1e -#define LSM6DS0_CTRL_REG5_XL 0x1f -#define LSM6DS0_CTRL_REG6_XL 0x20 -#define LSM6DS0_CTRL_REG7_XL 0x21 -#define LSM6DS0_CTRL_REG8 0x22 -#define LSM6DS0_CTRL_REG9 0x23 -#define LSM6DS0_CTRL_REG10 0x24 -#define LSM6DS0_INT_GEN_SRC_XL 0x26 -#define LSM6DS0_STATUS_REG 0x27 -#define LSM6DS0_OUT_X_L_XL 0x28 -#define LSM6DS0_OUT_X_H_XL 0x29 -#define LSM6DS0_OUT_Y_L_XL 0x2a -#define LSM6DS0_OUT_Y_H_XL 0x2b -#define LSM6DS0_OUT_Z_L_XL 0x2c -#define LSM6DS0_OUT_Z_H_XL 0x2d -#define LSM6DS0_FIFO_CTRL 0x2e -#define LSM6DS0_FIFO_SRC 0x2f -#define LSM6DS0_INT_GEN_CFG_G 0x30 -#define LSM6DS0_INT_GEN_THS_XH_G 0x31 -#define LSM6DS0_INT_GEN_THS_XL_G 0x32 -#define LSM6DS0_INT_GEN_THS_YH_G 0x33 -#define LSM6DS0_INT_GEN_THS_YL_G 0x34 -#define LSM6DS0_INT_GEN_THS_ZH_G 0x35 -#define LSM6DS0_INT_GEN_THS_ZL_G 0x36 -#define LSM6DS0_INT_GEN_DUR_G 0x37 - -#define LSM6DS0_DPS_SEL_245 (0 << 3) -#define LSM6DS0_DPS_SEL_500 BIT(3) -#define LSM6DS0_DPS_SEL_1000 (2 << 3) -#define LSM6DS0_DPS_SEL_2000 (3 << 3) -#define LSM6DS0_GSEL_2G (0 << 3) -#define LSM6DS0_GSEL_4G (2 << 3) -#define LSM6DS0_GSEL_8G (3 << 3) - -#define LSM6DS0_RANGE_MASK (3 << 3) - -#define LSM6DS0_ODR_PD (0 << 5) -#define LSM6DS0_ODR_10HZ BIT(5) -#define LSM6DS0_ODR_15HZ BIT(5) -#define LSM6DS0_ODR_50HZ (2 << 5) -#define LSM6DS0_ODR_59HZ (2 << 5) -#define LSM6DS0_ODR_119HZ (3 << 5) -#define LSM6DS0_ODR_238HZ (4 << 5) -#define LSM6DS0_ODR_476HZ (5 << 5) -#define LSM6DS0_ODR_952HZ (6 << 5) - -#define LSM6DS0_ODR_MASK (7 << 5) - -/* - * Register : STATUS_REG - * Address : 0X27 - */ -enum lsm6ds0_status { - LSM6DS0_STS_DOWN = 0x00, - LSM6DS0_STS_XLDA_UP = 0x01, - LSM6DS0_STS_GDA_UP = 0x02, -}; -#define LSM6DS0_STS_XLDA_MASK 0x01 -#define LSM6DS0_STS_GDA_MASK 0x02 - -/* - * Register : CTRL_REG8 - * Address : 0X22 - * Bit Group Name: BDU - */ -enum lsm6ds0_bdu { - LSM6DS0_BDU_DISABLE = 0x00, - LSM6DS0_BDU_ENABLE = 0x40, -}; -/* Sensor resolution in number of bits. This sensor has fixed resolution. */ -#define LSM6DS0_RESOLUTION 16 - -/* Min and Max sampling frequency in mHz */ -#define LSM6DS0_ACCEL_MIN_FREQ 14900 -#define LSM6DS0_ACCEL_MAX_FREQ MOTION_MAX_SENSOR_FREQUENCY(952000, 119000) - -#define LSM6DS0_GYRO_MIN_FREQ 14900 -#define LSM6DS0_GYRO_MAX_FREQ MOTION_MAX_SENSOR_FREQUENCY(952000, 119000) - -extern const struct accelgyro_drv lsm6ds0_drv; -struct lsm6ds0_data { - struct accelgyro_saved_data_t base; - int16_t offset[3]; -}; - -#endif /* __CROS_EC_ACCELGYRO_LSM6DS0_H */ diff --git a/driver/accelgyro_lsm6dsm.c b/driver/accelgyro_lsm6dsm.c deleted file mode 100644 index 3d0c717a9b..0000000000 --- a/driver/accelgyro_lsm6dsm.c +++ /dev/null @@ -1,852 +0,0 @@ -/* 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. - */ - -/** - * LSM6DSx (x is L/M/3) accelerometer and gyro module for Chrome EC - * 3D digital accelerometer & 3D digital gyroscope - * This driver supports both devices LSM6DSM and LSM6DSL - */ - -#include "driver/accelgyro_lsm6dsm.h" -#include "driver/mag_lis2mdl.h" -#include "hooks.h" -#include "hwtimer.h" -#include "mag_cal.h" -#include "math_util.h" -#include "motion_sense_fifo.h" -#include "queue.h" -#include "task.h" -#include "timer.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) - -#define IS_FSTS_EMPTY(s) ((s).len & LSM6DSM_FIFO_EMPTY) - -#ifndef FIFO_READ_LEN -#define FIFO_READ_LEN 0 -#endif - -#ifndef CONFIG_ACCEL_LSM6DSM_INT_EVENT -#define CONFIG_ACCEL_LSM6DSM_INT_EVENT 0 -#endif - -static volatile uint32_t last_interrupt_timestamp; - -/** - * Resets the lsm6dsm load fifo sensor states to the given timestamp. This - * should be called at the start of the fifo read sequence. - * - * @param s Pointer to the first sensor in the lsm6dsm (accelerometer). - * @param ts The timestamp to use for the interrupt timestamp. - */ -__maybe_unused static void reset_load_fifo_sensor_state( - struct motion_sensor_t *s, uint32_t ts) -{ - int i; - struct lsm6dsm_accel_fifo_state *fifo_state = - LSM6DSM_GET_DATA(s)->accel_fifo_state; - - for (i = 0; i < FIFO_DEV_NUM; i++) { - fifo_state->load_fifo_sensor_state[i].int_timestamp = ts; - fifo_state->load_fifo_sensor_state[i].sample_count = 0; - } -} - -/** - * Gets the dev_fifo enum value for a given sensor. - * - * @param s Pointer to the sensor in question. - * @return the dev_fifo enum value corresponding to the sensor. - */ -static inline enum dev_fifo get_fifo_type(const struct motion_sensor_t *s) -{ - static enum dev_fifo map[] = { - FIFO_DEV_ACCEL, - FIFO_DEV_GYRO, -#ifdef CONFIG_LSM6DSM_SEC_I2C - FIFO_DEV_MAG -#endif /* CONFIG_LSM6DSM_SEC_I2C */ - }; - return map[s->type]; -} - -/** - * Gets the sensor type associated with the dev_fifo enum. This type can be used - * to get the sensor number by using it as an offset from the first sensor in - * the lsm6dsm (the accelerometer). - * - * @param fifo_type The dev_fifo enum in question. - * @return the type of sensor represented by the fifo type. - */ -static inline uint8_t get_sensor_type(enum dev_fifo fifo_type) -{ - static uint8_t map[] = { - MOTIONSENSE_TYPE_GYRO, - MOTIONSENSE_TYPE_ACCEL, - MOTIONSENSE_TYPE_MAG, - }; - return map[fifo_type]; -} - -/** - * @return output base register for sensor - */ -static inline int get_xyz_reg(enum motionsensor_type type) -{ - return LSM6DSM_ACCEL_OUT_X_L_ADDR - - (LSM6DSM_ACCEL_OUT_X_L_ADDR - LSM6DSM_GYRO_OUT_X_L_ADDR) * type; -} - -/** - * Configure interrupt int 1 to fire handler for: - * - * FIFO threshold on watermark - * - * @accel: Motion sensor pointer to accelerometer. - */ -__maybe_unused static int config_interrupt(const struct motion_sensor_t *accel) -{ - int ret = EC_SUCCESS; - int int1_ctrl_val; - - ret = st_raw_read8(accel->port, accel->i2c_spi_addr_flags, - LSM6DSM_INT1_CTRL, &int1_ctrl_val); - if (ret != EC_SUCCESS) - return ret; - - if (IS_ENABLED(CONFIG_ACCEL_FIFO)) { - /* As soon as one sample is ready, trigger an interrupt. */ - ret = st_raw_write8(accel->port, accel->i2c_spi_addr_flags, - LSM6DSM_FIFO_CTRL1_ADDR, - OUT_XYZ_SIZE / sizeof(uint16_t)); - if (ret != EC_SUCCESS) - return ret; - int1_ctrl_val |= LSM6DSM_INT_FIFO_TH | LSM6DSM_INT_FIFO_OVR | - LSM6DSM_INT_FIFO_FULL; - } - - return st_raw_write8(accel->port, accel->i2c_spi_addr_flags, - LSM6DSM_INT1_CTRL, int1_ctrl_val); -} - - -/** - * fifo_disable - set fifo mode - * @accel: Motion sensor pointer: must be MOTIONSENSE_TYPE_ACCEL. - * @fmode: BYPASS or CONTINUOUS - */ -static int fifo_disable(const struct motion_sensor_t *accel) -{ - return st_raw_write8(accel->port, accel->i2c_spi_addr_flags, - LSM6DSM_FIFO_CTRL5_ADDR, 0x00); -} - -/** - * fifo_reset_pattern: called at each new FIFO pattern. - */ -static void fifo_reset_pattern(struct lsm6dsm_data *private) -{ - /* The fifo is ready to run. */ - memcpy(&private->accel_fifo_state->current, - &private->accel_fifo_state->config, - sizeof(struct lsm6dsm_fifo_data)); - private->accel_fifo_state->next_in_pattern = FIFO_DEV_INVALID; -} - -/** - * fifo_enable - Configure internal FIFO parameters - * @accel must be the accelerometer sensor. - * - * Configure FIFO decimators to have every time the right pattern - * with acc/gyro - */ -static int fifo_enable(const struct motion_sensor_t *accel) -{ - const struct motion_sensor_t *s; - int err, i, rate; - uint8_t decimators[FIFO_DEV_NUM] = { 0 }; - unsigned int odrs[FIFO_DEV_NUM]; - unsigned int min_odr = LSM6DSM_ODR_MAX_VAL; - unsigned int max_odr = 0; - uint8_t odr_reg_val; - struct lsm6dsm_data *private = LSM6DSM_GET_DATA(accel); - struct lsm6dsm_accel_fifo_state *fifo_state = private->accel_fifo_state; - /* In FIFO sensors are mapped in a different way. */ - uint8_t agm_maps[] = { - MOTIONSENSE_TYPE_GYRO, - MOTIONSENSE_TYPE_ACCEL, - MOTIONSENSE_TYPE_MAG, - }; - - - /* Search for min and max odr values for acc, gyro. */ - for (i = FIFO_DEV_GYRO; i < FIFO_DEV_NUM; i++) { - /* Check if sensor enabled with ODR. */ - s = accel + agm_maps[i]; - rate = s->drv->get_data_rate(s); - if (rate > 0) { - min_odr = MIN(min_odr, rate); - max_odr = MAX(max_odr, rate); - } - odrs[i] = rate; - } - - if (max_odr == 0) { - /* Leave FIFO disabled. */ - return EC_SUCCESS; - } - - /* FIFO ODR must be set before the decimation factors */ - odr_reg_val = LSM6DSM_ODR_TO_REG(max_odr) << - LSM6DSM_FIFO_CTRL5_ODR_OFF; - err = st_raw_write8(accel->port, accel->i2c_spi_addr_flags, - LSM6DSM_FIFO_CTRL5_ADDR, odr_reg_val); - - /* Scan all sensors configuration to calculate FIFO decimator. */ - fifo_state->config.total_samples_in_pattern = 0; - for (i = FIFO_DEV_GYRO; i < FIFO_DEV_NUM; i++) { - if (odrs[i] > 0) { - fifo_state->config.samples_in_pattern[i] = - odrs[i] / min_odr; - decimators[i] = - LSM6DSM_FIFO_DECIMATOR(max_odr / odrs[i]); - fifo_state->config.total_samples_in_pattern += - fifo_state->config.samples_in_pattern[i]; - } else { - /* Not in FIFO if sensor disabled. */ - fifo_state->config.samples_in_pattern[i] = 0; - } - } - st_raw_write8(accel->port, accel->i2c_spi_addr_flags, - LSM6DSM_FIFO_CTRL3_ADDR, - (decimators[FIFO_DEV_GYRO] << LSM6DSM_FIFO_DEC_G_OFF) | - (decimators[FIFO_DEV_ACCEL] << LSM6DSM_FIFO_DEC_XL_OFF)); -#ifdef CONFIG_LSM6DSM_SEC_I2C - st_raw_write8(accel->port, accel->i2c_spi_addr_flags, - LSM6DSM_FIFO_CTRL4_ADDR, - decimators[FIFO_DEV_MAG]); - - /* - * FIFO ODR is limited by odr of gyro or accel. - * If we are sampling magnetometer faster than gyro or accel, - * bump up ODR of accel. Thanks to decimation we will still measure at - * the specified ODR. - * Contrary to gyroscope, sampling faster will not affect measurements. - * Set the ODR behind the back of set/get_data_rate. - * - * First samples after ODR changes must be thrown out [See - * AN4987, section 3.9]. - * When increasing accel ODR, the FIFO is going to drop samples, - * - except the first one after ODR change. - * When decreasing accel ODR, we don't need to drop sample if - * frequency is less than 52Hz. - * At most, we need to drop one sample, but Android requirement specify - * that chaning one sensor ODR should not affect other sensors. - * Leave the bad sample alone, it will be a single glitch in the - * accelerometer data stream. - */ - if (max_odr > MAX(odrs[FIFO_DEV_ACCEL], odrs[FIFO_DEV_GYRO])) { - st_write_data_with_mask(accel, LSM6DSM_ODR_REG(accel->type), - LSM6DSM_ODR_MASK, - LSM6DSM_ODR_TO_REG(max_odr)); - } else { - st_write_data_with_mask(accel, LSM6DSM_ODR_REG(accel->type), - LSM6DSM_ODR_MASK, - LSM6DSM_ODR_TO_REG(odrs[FIFO_DEV_ACCEL])); - } -#endif /* CONFIG_MAG_LSM6DSM_LIS2MDL */ - /* - * After ODR and decimation values are set, continuous mode can be - * enabled - */ - err = st_raw_write8(accel->port, accel->i2c_spi_addr_flags, - LSM6DSM_FIFO_CTRL5_ADDR, - odr_reg_val | LSM6DSM_FIFO_MODE_CONTINUOUS_VAL); - if (err != EC_SUCCESS) - return err; - fifo_reset_pattern(private); - return EC_SUCCESS; -} - -/* - * Must order FIFO read based on ODR: - * For example Acc @ 52 Hz, Gyro @ 26 Hz Mag @ 13 Hz in FIFO we have - * for each pattern this data samples: - * ________ _______ _______ _______ ________ _______ _______ - * | Gyro_0 | Acc_0 | Mag_0 | Acc_1 | Gyro_1 | Acc_2 | Acc_3 | - * |________|_______|_______|_______|________|_______|_______| - * - * Total samples for each pattern: 2 Gyro, 4 Acc, 1 Mag. - * - * Returns dev_fifo enum value of next sample to process - */ -static int fifo_next(struct lsm6dsm_data *private) -{ - int next_id; - struct lsm6dsm_accel_fifo_state *fifo_state = private->accel_fifo_state; - - if (fifo_state->current.total_samples_in_pattern == 0) - fifo_reset_pattern(private); - - if (fifo_state->current.total_samples_in_pattern == 0) { - /* - * Not expected we are supposed to be called to process FIFO - * data. - */ - CPRINTS("FIFO empty pattern"); - return FIFO_DEV_INVALID; - } - - for (next_id = fifo_state->next_in_pattern + 1; 1; next_id++) { - if (next_id == FIFO_DEV_NUM) - next_id = FIFO_DEV_GYRO; - if (fifo_state->current.samples_in_pattern[next_id] != 0) { - fifo_state->current.samples_in_pattern[next_id]--; - fifo_state->current.total_samples_in_pattern--; - fifo_state->next_in_pattern = next_id; - return next_id; - } - } - /* Will never happen. */ - return FIFO_DEV_INVALID; -} - -/** - * push_fifo_data - Scan data pattern and push upside - */ -static void push_fifo_data(struct motion_sensor_t *accel, uint8_t *fifo, - uint16_t flen, - uint32_t timestamp) -{ - struct motion_sensor_t *s; - struct lsm6dsm_data *private = LSM6DSM_GET_DATA(accel); - - while (flen > 0) { - struct ec_response_motion_sensor_data vect; - int id; - int *axis; - int next_fifo = fifo_next(private); - /* - * This should never happen, but it could. There will be a - * report from inside fifo_next about it, so no extra message - * required here. - */ - if (next_fifo == FIFO_DEV_INVALID) { - return; - } - - id = get_sensor_type(next_fifo); - if (private->accel_fifo_state->samples_to_discard[id] > 0) { - private->accel_fifo_state->samples_to_discard[id]--; - } else { - s = accel + id; - axis = s->raw_xyz; - - /* Apply precision, sensitivity and rotation. */ -#ifdef CONFIG_MAG_LSM6DSM_LIS2MDL - if (s->type == MOTIONSENSE_TYPE_MAG) { - lis2mdl_normalize(s, axis, fifo); - rotate(axis, *s->rot_standard_ref, axis); - } else -#endif - { - st_normalize(s, axis, fifo); - } - - - vect.data[X] = axis[X]; - vect.data[Y] = axis[Y]; - vect.data[Z] = axis[Z]; - - vect.flags = 0; - vect.sensor_num = s - motion_sensors; - motion_sense_fifo_stage_data(&vect, s, 3, timestamp); - } - - fifo += OUT_XYZ_SIZE; - flen -= OUT_XYZ_SIZE; - } -} - -static int load_fifo(struct motion_sensor_t *s, const struct fstatus *fsts, - uint32_t *last_fifo_read_ts) -{ - uint32_t interrupt_timestamp = last_interrupt_timestamp; - int err, left, length; - uint8_t fifo[FIFO_READ_LEN]; - - /* Reset the load_fifo_sensor_state so we can start a new read. */ - reset_load_fifo_sensor_state(s, interrupt_timestamp); - - /* - * DIFF[11:0] are number of unread uint16 in FIFO - * mask DIFF and compute total byte len to read from FIFO. - */ - left = fsts->len & LSM6DSM_FIFO_DIFF_MASK; - left *= sizeof(uint16_t); - left = (left / OUT_XYZ_SIZE) * OUT_XYZ_SIZE; - - /* - * TODO(b/122912601): phaser360: Investigate Standard Deviation error - * during CtsSensorTests - * - check "pattern" register versus where code thinks it is parsing - */ - - /* Push all data on upper side. */ - do { - /* Fit len to pre-allocated static buffer. */ - if (left > FIFO_READ_LEN) - length = FIFO_READ_LEN; - else - length = left; - - /* Read data and copy in buffer. */ - err = st_raw_read_n_noinc(s->port, s->i2c_spi_addr_flags, - LSM6DSM_FIFO_DATA_ADDR, - fifo, length); - *last_fifo_read_ts = __hw_clock_source_read(); - if (err != EC_SUCCESS) - return err; - - /* - * Manage patterns and push data. Data is pushed with the - * timestamp of the interrupt that got us into this function - * in the first place. This avoids a potential race condition - * where we empty the FIFO, and a new IRQ comes in between - * reading the last sample and pushing it into the FIFO. - */ - - push_fifo_data(s, fifo, length, interrupt_timestamp); - left -= length; - } while (left > 0); - - motion_sense_fifo_commit_data(); - - return EC_SUCCESS; -} - -static int is_fifo_empty(struct motion_sensor_t *s, struct fstatus *fsts) -{ - int res; - - if (s->flags & MOTIONSENSE_FLAG_INT_SIGNAL) - return gpio_get_level(s->int_signal); - CPRINTS("Interrupt signal not set for %s", s->name); - res = st_raw_read_n_noinc(s->port, s->i2c_spi_addr_flags, - LSM6DSM_FIFO_STS1_ADDR, - (int8_t *)fsts, sizeof(*fsts)); - /* If we failed to read the FIFO size assume empty. */ - if (res != EC_SUCCESS) - return 1; - return IS_FSTS_EMPTY(*fsts); -} - -static void handle_interrupt_for_fifo(uint32_t ts) -{ - if (IS_ENABLED(CONFIG_ACCEL_FIFO) && - time_after(ts, last_interrupt_timestamp)) - last_interrupt_timestamp = ts; - task_set_event(TASK_ID_MOTIONSENSE, - CONFIG_ACCEL_LSM6DSM_INT_EVENT, 0); -} - -/** - * lsm6dsm_interrupt - interrupt from int1/2 pin of sensor - */ -void lsm6dsm_interrupt(enum gpio_signal signal) -{ - handle_interrupt_for_fifo(__hw_clock_source_read()); -} - -/** - * irq_handler - bottom half of the interrupt stack - */ -__maybe_unused static int irq_handler( - struct motion_sensor_t *s, uint32_t *event) -{ - int ret = EC_SUCCESS; - - if ((s->type != MOTIONSENSE_TYPE_ACCEL) || - (!(*event & CONFIG_ACCEL_LSM6DSM_INT_EVENT))) - return EC_ERROR_NOT_HANDLED; - - if (IS_ENABLED(CONFIG_ACCEL_FIFO)) { - struct fstatus fsts; - uint32_t last_fifo_read_ts; - uint32_t triggering_interrupt_timestamp = - last_interrupt_timestamp; - - /* Read how many data pattern on FIFO to read and pattern. */ - ret = st_raw_read_n_noinc(s->port, s->i2c_spi_addr_flags, - LSM6DSM_FIFO_STS1_ADDR, - (uint8_t *)&fsts, sizeof(fsts)); - if (ret != EC_SUCCESS) - return ret; - last_fifo_read_ts = __hw_clock_source_read(); - if (fsts.len & (LSM6DSM_FIFO_DATA_OVR | LSM6DSM_FIFO_FULL)) - CPRINTS("%s FIFO Overrun: %04x", s->name, fsts.len); - if (!IS_FSTS_EMPTY(fsts)) - ret = load_fifo(s, &fsts, &last_fifo_read_ts); - - /* - * Check if FIFO isn't empty and we never got an interrupt. - * This can happen if new entries were added to the FIFO after - * the count was read, but before the FIFO was cleared out. - * In the long term it might be better to use the last - * spread timestamp instead. - */ - if (!is_fifo_empty(s, &fsts) && - triggering_interrupt_timestamp == last_interrupt_timestamp) - handle_interrupt_for_fifo(last_fifo_read_ts); - } - - return ret; -} - -/** - * set_range - set full scale range - * @s: Motion sensor pointer - * @range: Range - * @rnd: Round up/down flag - * Note: Range is sensitivity/gain for speed purpose - */ -static int set_range(const struct motion_sensor_t *s, int range, int rnd) -{ - int err; - uint8_t ctrl_reg, reg_val; - struct stprivate_data *data = s->drv_data; - int newrange = range; - - switch (s->type) { - case MOTIONSENSE_TYPE_ACCEL: - /* Adjust and check rounded value for acc. */ - if (rnd && (newrange < LSM6DSM_ACCEL_NORMALIZE_FS(newrange))) - newrange *= 2; - - if (newrange > LSM6DSM_ACCEL_FS_MAX_VAL) - newrange = LSM6DSM_ACCEL_FS_MAX_VAL; - - reg_val = LSM6DSM_ACCEL_FS_REG(newrange); - break; - case MOTIONSENSE_TYPE_GYRO: - /* Adjust and check rounded value for gyro. */ - reg_val = LSM6DSM_GYRO_FS_REG(range); - if (rnd && (range > LSM6DSM_GYRO_NORMALIZE_FS(reg_val))) - reg_val++; - - if (reg_val > LSM6DSM_GYRO_FS_MAX_REG_VAL) - reg_val = LSM6DSM_GYRO_FS_MAX_REG_VAL; - newrange = LSM6DSM_GYRO_NORMALIZE_FS(reg_val); - break; - default: - return EC_RES_INVALID_PARAM; - } - - ctrl_reg = LSM6DSM_RANGE_REG(s->type); - mutex_lock(s->mutex); - err = st_write_data_with_mask(s, ctrl_reg, LSM6DSM_RANGE_MASK, reg_val); - if (err == EC_SUCCESS) - /* Save internally gain for speed optimization. */ - data->base.range = newrange; - mutex_unlock(s->mutex); - return err; -} - -/** - * get_range - get full scale range - * @s: Motion sensor pointer - * - * For mag range is fixed to LIS2MDL_RANGE by hardware - */ -static int get_range(const struct motion_sensor_t *s) -{ - struct stprivate_data *data = s->drv_data; - - return data->base.range; -} - -/** - * lsm6dsm_set_data_rate - * @s: Motion sensor pointer - * @range: Rate (mHz) - * @rnd: Round up/down flag - * - * For mag in cascade with lsm6dsm/l we use acc trigger and FIFO decimators - */ -int lsm6dsm_set_data_rate(const struct motion_sensor_t *s, int rate, int rnd) -{ - struct stprivate_data *data = s->drv_data; - const struct motion_sensor_t *accel = IS_ENABLED(CONFIG_ACCEL_FIFO) ? - LSM6DSM_MAIN_SENSOR(s) : NULL; - struct lsm6dsm_data *private = IS_ENABLED(CONFIG_ACCEL_FIFO) ? - LSM6DSM_GET_DATA(accel) : NULL; - int ret = EC_SUCCESS, normalized_rate = 0; - uint8_t ctrl_reg, reg_val = 0; - - if (IS_ENABLED(CONFIG_ACCEL_FIFO)) { - /* FIFO must be disabled before setting any ODR values */ - ret = fifo_disable(accel); - if (ret != EC_SUCCESS) { - CPRINTS("Failed to disable FIFO. Error: %d", ret); - return ret; - } - } - - if (rate > 0) { - reg_val = LSM6DSM_ODR_TO_REG(rate); - normalized_rate = LSM6DSM_REG_TO_ODR(reg_val); - - if (rnd && (normalized_rate < rate)) { - reg_val++; - normalized_rate = LSM6DSM_REG_TO_ODR(reg_val); - } - if (normalized_rate < LSM6DSM_ODR_MIN_VAL || - normalized_rate > LSM6DSM_ODR_MAX_VAL) - return EC_RES_INVALID_PARAM; - } - -#ifdef CONFIG_MAG_LSM6DSM_LIS2MDL - /* - * TODO(b:110143516) Improve data rate selection: - * Sensor is always running at 100Hz, even when not used. - */ - if (s->type == MOTIONSENSE_TYPE_MAG) { - struct mag_cal_t *cal = LIS2MDL_CAL(s); - - init_mag_cal(cal); - /* - * Magnetometer ODR is calculating at 100Hz, but we are reading - * less often. - */ - if (normalized_rate > 0) - cal->batch_size = MAX( - MAG_CAL_MIN_BATCH_SIZE, - (normalized_rate * 1000) / - MAG_CAL_MIN_BATCH_WINDOW_US); - else - cal->batch_size = 0; - CPRINTS("Batch size: %d", cal->batch_size); - mutex_lock(s->mutex); - } else -#endif - { - mutex_lock(s->mutex); - ctrl_reg = LSM6DSM_ODR_REG(s->type); - ret = st_write_data_with_mask(s, ctrl_reg, LSM6DSM_ODR_MASK, - reg_val); - } - if (ret == EC_SUCCESS) { - data->base.odr = normalized_rate; - if (IS_ENABLED(CONFIG_ACCEL_FIFO)) { - struct lsm6dsm_accel_fifo_state *fifo_state = - private->accel_fifo_state; - fifo_state->samples_to_discard[s->type] = - LSM6DSM_DISCARD_SAMPLES; - fifo_state->load_fifo_sensor_state[get_fifo_type(s)] - .sample_rate = normalized_rate == 0 - ? 0 : SECOND * 1000 / normalized_rate; - ret = fifo_enable(accel); - if (ret != EC_SUCCESS) - CPRINTS("Failed to enable FIFO. Error: %d", - ret); - } - } - - mutex_unlock(s->mutex); - return ret; -} - -static int is_data_ready(const struct motion_sensor_t *s, int *ready) -{ - int ret, tmp; - - ret = st_raw_read8(s->port, s->i2c_spi_addr_flags, - LSM6DSM_STATUS_REG, &tmp); - if (ret != EC_SUCCESS) { - CPRINTS("%s type:0x%X RS Error", s->name, s->type); - return ret; - } - - if (MOTIONSENSE_TYPE_ACCEL == s->type) - *ready = (LSM6DSM_STS_XLDA_UP == (tmp & LSM6DSM_STS_XLDA_MASK)); - else - *ready = (LSM6DSM_STS_GDA_UP == (tmp & LSM6DSM_STS_GDA_MASK)); - - return EC_SUCCESS; -} - -/* - * Is not very efficient to collect the data in read: better have an interrupt - * and collect the FIFO, even if it has one item: we don't have to check if the - * sensor is ready (minimize I2C access). - */ -static int read(const struct motion_sensor_t *s, intv3_t v) -{ - uint8_t raw[OUT_XYZ_SIZE]; - uint8_t xyz_reg; - int ret, tmp = 0; - - ret = is_data_ready(s, &tmp); - if (ret != EC_SUCCESS) - return ret; - - /* - * If sensor data is not ready, return the previous read data. - * Note: return success so that motion senor task can read again - * to get the latest updated sensor data quickly. - */ - if (!tmp) { - if (v != s->raw_xyz) - memcpy(v, s->raw_xyz, sizeof(s->raw_xyz)); - return EC_SUCCESS; - } - - xyz_reg = get_xyz_reg(s->type); - - /* Read data bytes starting at xyz_reg. */ - ret = st_raw_read_n_noinc(s->port, s->i2c_spi_addr_flags, - xyz_reg, raw, OUT_XYZ_SIZE); - if (ret != EC_SUCCESS) - return ret; - - /* Apply precision, sensitivity and rotation vector. */ - st_normalize(s, v, raw); - return EC_SUCCESS; -} - -static int init(const struct motion_sensor_t *s) -{ - int ret = 0, tmp; - struct stprivate_data *data = s->drv_data; - uint8_t ctrl_reg, reg_val = 0; - - ret = st_raw_read8(s->port, s->i2c_spi_addr_flags, - LSM6DSM_WHO_AM_I_REG, &tmp); - if (ret != EC_SUCCESS) - return EC_ERROR_UNKNOWN; - - if (tmp != LSM6DS3_WHO_AM_I && tmp != LSM6DSM_WHO_AM_I) { - /* Unrecognized sensor */ - CPRINTS("Unknown WHO_AM_I value: 0x%x", tmp); - return EC_ERROR_ACCESS_DENIED; - } - - /* - * This sensor can be powered through an EC reboot, so the state of the - * sensor is unknown here so reset it - * LSM6DSM/L supports both accel & gyro features - * Board will see two virtual sensor devices: accel & gyro - * Requirement: Accel need be init before gyro and mag - */ - if (s->type == MOTIONSENSE_TYPE_ACCEL) { - mutex_lock(s->mutex); - - /* Software reset procedure. */ - reg_val = LSM6DSM_ODR_TO_REG(LSM6DSM_ODR_MIN_VAL); - ctrl_reg = LSM6DSM_ODR_REG(MOTIONSENSE_TYPE_ACCEL); - - /* Power OFF gyro. */ - ret = st_raw_write8(s->port, s->i2c_spi_addr_flags, - LSM6DSM_CTRL2_ADDR, 0); - if (ret != EC_SUCCESS) - goto err_unlock; - - /* Power ON Accel. */ - ret = st_raw_write8(s->port, s->i2c_spi_addr_flags, - ctrl_reg, reg_val); - if (ret != EC_SUCCESS) - goto err_unlock; - - /* Software reset. */ - ret = st_raw_write8(s->port, s->i2c_spi_addr_flags, - LSM6DSM_CTRL3_ADDR, LSM6DSM_SW_RESET); - if (ret != EC_SUCCESS) - goto err_unlock; - -#ifdef CONFIG_LSM6DSM_SEC_I2C - /* - * Reboot to reload memory content as pass-through mode can get - * stuck. - * Direct to the AN: See "AN4987 - LSM6DSM: always-on 3D - * accelerometer and 3D gyroscope". - */ - - /* Power ON Accel. */ - ret = st_raw_write8(s->port, s->i2c_spi_addr_flags, - ctrl_reg, reg_val); - if (ret != EC_SUCCESS) - goto err_unlock; - - ret = st_raw_write8(s->port, s->i2c_spi_addr_flags, - LSM6DSM_CTRL3_ADDR, LSM6DSM_BOOT); - if (ret != EC_SUCCESS) - goto err_unlock; - - /* - * Refer to AN4987, wait 15ms for accelerometer to doing full - * reboot. - */ - msleep(15); - - /* Power OFF Accel. */ - ret = st_raw_write8(s->port, s->i2c_spi_addr_flags, - ctrl_reg, 0); - if (ret != EC_SUCCESS) - goto err_unlock; -#endif - - /* - * Output data not updated until have been read. - * Prefer interrupt to be active low. - */ - ret = st_raw_write8(s->port, s->i2c_spi_addr_flags, - LSM6DSM_CTRL3_ADDR, - LSM6DSM_BDU - | LSM6DSM_H_L_ACTIVE - | LSM6DSM_IF_INC); - if (ret != EC_SUCCESS) - goto err_unlock; - - if (IS_ENABLED(CONFIG_ACCEL_FIFO)) { - ret = fifo_disable(s); - if (ret != EC_SUCCESS) - goto err_unlock; - } - -#ifdef CONFIG_ACCEL_INTERRUPTS - ret = config_interrupt(s); - if (ret != EC_SUCCESS) - goto err_unlock; -#endif /* CONFIG_ACCEL_INTERRUPTS */ - - mutex_unlock(s->mutex); - } - - /* Set default resolution common to acc and gyro. */ - data->resol = LSM6DSM_RESOLUTION; - return sensor_init_done(s); - -err_unlock: - mutex_unlock(s->mutex); - CPRINTS("%s: MS Init type:0x%X Error", s->name, s->type); - return ret; -} - -const struct accelgyro_drv lsm6dsm_drv = { - .init = init, - .read = read, - .set_range = set_range, - .get_range = get_range, - .get_resolution = st_get_resolution, - .set_data_rate = lsm6dsm_set_data_rate, - .get_data_rate = st_get_data_rate, - .set_offset = st_set_offset, - .get_offset = st_get_offset, -#ifdef CONFIG_ACCEL_INTERRUPTS - .irq_handler = irq_handler, -#endif /* CONFIG_ACCEL_INTERRUPTS */ -}; diff --git a/driver/accelgyro_lsm6dsm.h b/driver/accelgyro_lsm6dsm.h deleted file mode 100644 index f63f6af4a0..0000000000 --- a/driver/accelgyro_lsm6dsm.h +++ /dev/null @@ -1,400 +0,0 @@ -/* 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. - */ - -/* LSM6DSM (also LSM6DSL) Accel and Gyro driver for Chrome EC */ - -#ifndef __CROS_EC_ACCELGYRO_LSM6DSM_H -#define __CROS_EC_ACCELGYRO_LSM6DSM_H - -#include "stm_mems_common.h" -#include "mag_cal.h" -#include "mag_bmm150.h" -#include "mag_lis2mdl.h" - -/* - * 7-bit address is 110101xb. Where 'x' is determined - * by the voltage on the ADDR pin - */ -#define LSM6DSM_ADDR0_FLAGS 0x6a -#define LSM6DSM_ADDR1_FLAGS 0x6b - -/* COMMON DEFINE FOR ACCEL-GYRO SENSORS */ -#define LSM6DSM_EN_BIT 0x01 -#define LSM6DSM_DIS_BIT 0x00 - -/* Access to embedded sensor hub register bank */ -#define LSM6DSM_FUNC_CFG_ACC_ADDR 0x01 -#define LSM6DSM_FUNC_CFG_EN 0x80 -#define LSM6DSM_FUNC_CFG_EN_B 0x20 - -/* FIFO decimator registers and bitmask */ -#define LSM6DSM_FIFO_CTRL1_ADDR 0x06 - -/* Output data rate registers and masks */ -#define LSM6DSM_ODR_REG(_sensor) \ - (LSM6DSM_CTRL1_ADDR + _sensor) -#define LSM6DSM_ODR_MASK 0xf0 - -#define LSM6DSM_FIFO_CTRL2_ADDR 0x07 - -#define LSM6DSM_FIFO_CTRL3_ADDR 0x08 -#define LSM6DSM_FIFO_DEC_XL_OFF 0 -#define LSM6DSM_FIFO_DEC_G_OFF 3 - -#define LSM6DSM_FIFO_CTRL4_ADDR 0x09 - -#define LSM6DSM_FIFO_DECIMATOR(_dec) \ - (_dec < 8 ? _dec : (2 + __builtin_ctz(_dec))) - -/* Hardware FIFO size in byte */ -#define LSM6DSM_MAX_FIFO_SIZE 4096 -#define LSM6DSM_MAX_FIFO_LENGTH (LSM6DSM_MAX_FIFO_SIZE / OUT_XYZ_SIZE) - -#define LSM6DSM_FIFO_CTRL5_ADDR 0x0a -#define LSM6DSM_FIFO_CTRL5_ODR_OFF 3 -#define LSM6DSM_FIFO_CTRL5_ODR_MASK \ - (0xf << LSM6DSM_FIFO_CTRL5_ODR_OFF) -#define LSM6DSM_FIFO_CTRL5_MODE_MASK 0x07 - -#define LSM6DSM_INT1_CTRL 0x0d -#define LSM6DSM_INT_FIFO_TH 0x08 -#define LSM6DSM_INT_FIFO_OVR 0x10 -#define LSM6DSM_INT_FIFO_FULL 0x20 -#define LSM6DSM_INT_SIGMO 0x40 - -/* Who Am I */ -#define LSM6DSM_WHO_AM_I_REG 0x0f -/* LSM6DSM/LSM6DSL/LSM6DS3TR-C */ -#define LSM6DSM_WHO_AM_I 0x6a -/* LSM6DS3 */ -#define LSM6DS3_WHO_AM_I 0x69 - -#define LSM6DSM_CTRL1_ADDR 0x10 -#define LSM6DSM_XL_ODR_MASK 0xf0 - -#define LSM6DSM_CTRL2_ADDR 0x11 -#define LSM6DSM_CTRL3_ADDR 0x12 -#define LSM6DSM_SW_RESET 0x01 -#define LSM6DSM_IF_INC 0x04 -#define LSM6DSM_PP_OD 0x10 -#define LSM6DSM_H_L_ACTIVE 0x20 -#define LSM6DSM_BDU 0x40 -#define LSM6DSM_BOOT 0x80 - -#define LSM6DSM_CTRL4_ADDR 0x13 -#define LSM6DSM_INT2_ON_INT1_MASK 0x20 - -#define LSM6DSM_CTRL6_ADDR 0x15 -#define LSM6DSM_CTRL7_ADDR 0x16 - -#define LSM6DSM_CTRL10_ADDR 0x19 -#define LSM6DSM_FUNC_EN_MASK 0x04 -#define LSM6DSM_SIG_MOT_MASK 0x01 -#define LSM6DSM_EMBED_FUNC_EN 0x04 -#define LSM6DSM_SIG_MOT_EN 0x01 - -/* Master mode configuration register */ -#define LSM6DSM_MASTER_CFG_ADDR 0x1a -#define LSM6DSM_PASSTROUGH_MASK 0x1f -#define LSM6DSM_EXT_TRIGGER_EN 0x10 -#define LSM6DSM_PULLUP_EN 0x08 -#define LSM6DSM_I2C_PASS_THRU_MODE 0x04 -#define LSM6DSM_I2C_MASTER_ON 0x01 - -#define LSM6DSM_TAP_SRC_ADDR 0x1c -#define LSM6DSM_STAP_DETECT 0x20 -#define LSM6DSM_DTAP_DETECT 0x10 - -#define LSM6DSM_STATUS_REG 0x1e - -#define LSM6DSM_GYRO_OUT_X_L_ADDR 0x22 -#define LSM6DSM_ACCEL_OUT_X_L_ADDR 0x28 - -#define LSM6DSM_SENSORHUB1_REG 0x2e - -#define LSM6DSM_FIFO_STS1_ADDR 0x3a -#define LSM6DSM_FIFO_STS2_ADDR 0x3b -#define LSM6DSM_FIFO_DIFF_MASK 0x0fff -#define LSM6DSM_FIFO_EMPTY 0x1000 -#define LSM6DSM_FIFO_FULL 0x2000 -#define LSM6DSM_FIFO_DATA_OVR 0x4000 -#define LSM6DSM_FIFO_WATERMARK 0x8000 -#define LSM6DSM_FIFO_NODECIM 0x01 - -/* Out data register */ -#define LSM6DSM_FIFO_DATA_ADDR 0x3e - -/* Registers value for supported FIFO mode */ -#define LSM6DSM_FIFO_MODE_BYPASS_VAL 0x00 -#define LSM6DSM_FIFO_MODE_CONTINUOUS_VAL 0x06 - -#define LSM6DSM_FUNC_SRC1_ADDR 0x53 -#define LSM6DSM_SENSORHUB_END_OP 0x01 -#define LSM6DSM_SIGN_MOTION_IA 0x40 - -#define LSM6DSM_LIR_ADDR 0x58 -#define LSM6DSM_LIR_MASK 0x01 -#define LSM6DSM_EN_INT 0x80 -#define LSM6DSM_EN_TAP 0x0e -#define LSM6DSM_TAP_MASK 0x8e - -#define LSM6DSM_TAP_THS_6D 0x59 -#define LSM6DSM_D4D_EN_MASK 0x80 -#define LSM6DSM_TAP_TH_MASK 0x1f - -#define LSM6DSM_INT_DUR2_ADDR 0x5a -#define LSM6DSM_TAP_DUR_MASK 0xf0 -#define LSM6DSM_TAP_QUIET_MASK 0x0c - -#define LSM6DSM_WUP_THS_ADDR 0x5b -#define LSM6DSM_S_D_TAP_MASK 0x80 -#define LSM6DSM_STAP_EN 0 -#define LSM6DSM_DTAP_EN 1 - -#define LSM6DSM_MD1_CFG_ADDR 0x5e -#define LSM6DSM_INT1_STAP 0x40 -#define LSM6DSM_INT1_DTAP 0x08 - -/* Register values for Sensor Hub Slave 0 / Bank A */ -#define LSM6DSM_SLV0_ADD_ADDR 0x02 -#define LSM6DSM_SLV0_ADDR_SHFT 1 -#define LSM6DSM_SLV0_ADDR_MASK 0xfe -#define LSM6DSM_SLV0_RD_BIT 0x01 - -#define LSM6DSM_SLV0_SUBADD_ADDR 0x03 - -#define LSM6DSM_SLV0_CONFIG_ADDR 0x04 -#define LSM6DSM_SLV0_SLV_RATE_SHFT 6 -#define LSM6DSM_SLV0_SLV_RATE_MASK 0xc0 -#define LSM6DSM_SLV0_AUX_SENS_SHFT 4 -#define LSM6DSM_SLV0_AUX_SENS_MASK 0x30 -#define LSM6DSM_SLV0_NUM_OPS_MASK 0x07 - -#define LSM6DSM_SLV1_CONFIG_ADDR 0x07 -#define LSM6DSM_SLV0_WR_ONCE_MASK 0x20 - -#define LSM6DSM_DATA_WRITE_SUB_SLV0_ADDR 0x0e - -/* Define device available in FIFO pattern */ -enum dev_fifo { - FIFO_DEV_INVALID = -1, - FIFO_DEV_GYRO = 0, - FIFO_DEV_ACCEL, -#ifdef CONFIG_LSM6DSM_SEC_I2C - FIFO_DEV_MAG, -#endif - FIFO_DEV_NUM, -}; - -struct fstatus { - uint16_t len; - uint16_t pattern; -}; - -/* Absolute maximum rate for acc and gyro sensors */ -#define LSM6DSM_ODR_MIN_VAL 13000 -#define LSM6DSM_ODR_MAX_VAL \ - MOTION_MAX_SENSOR_FREQUENCY(416000, LSM6DSM_ODR_MIN_VAL) - -/* ODR reg value from selected data rate in mHz */ -#define LSM6DSM_ODR_TO_REG(_odr) (__fls(_odr / LSM6DSM_ODR_MIN_VAL) + 1) - -/* normalized ODR value from selected data rate in mHz */ -#define LSM6DSM_REG_TO_ODR(_reg) (LSM6DSM_ODR_MIN_VAL << (_reg - 1)) - -/* Full Scale range value and gain for Acc */ -#define LSM6DSM_FS_LIST_NUM 4 - -#define LSM6DSM_ACCEL_FS_ADDR 0x10 -#define LSM6DSM_ACCEL_FS_MASK 0x0c - -#define LSM6DSM_ACCEL_FS_2G_VAL 0x00 -#define LSM6DSM_ACCEL_FS_4G_VAL 0x02 -#define LSM6DSM_ACCEL_FS_8G_VAL 0x03 -#define LSM6DSM_ACCEL_FS_16G_VAL 0x01 - -#define LSM6DSM_ACCEL_FS_MAX_VAL 16 - -/* Accel Reg value from Full Scale */ -#define LSM6DSM_ACCEL_FS_REG(_fs) \ - (_fs == 2 ? LSM6DSM_ACCEL_FS_2G_VAL : \ - _fs == 16 ? LSM6DSM_ACCEL_FS_16G_VAL : \ - __fls(_fs)) - -/* Accel normalized FS value from Full Scale */ -#define LSM6DSM_ACCEL_NORMALIZE_FS(_fs) (1 << __fls(_fs)) - -/* Full Scale range value and gain for Gyro */ -#define LSM6DSM_GYRO_FS_ADDR 0x11 -#define LSM6DSM_GYRO_FS_MASK 0x0c - - -/* Supported gyroscope ranges: - * name(dps) | register | gain(udps/LSB) | actual value(dps) - * 250 | 0 | 8750 | 286.72 - * 500 | 1 | 17500 | 573.44 - * 1000 | 2 | 35000 | 1146.88 - * 2000 | 3 | 70000 | 2293.76 - */ -#define LSM6DSM_GYRO_FS_MIN_VAL_MDPS ((8750 << 15) / 1000) -#define LSM6DSM_GYRO_FS_MAX_REG_VAL 3 - -/* Gyro Reg value for Full Scale selection */ -#define LSM6DSM_GYRO_FS_REG(_fs) \ - __fls(MAX(1, (_fs * 1000) / LSM6DSM_GYRO_FS_MIN_VAL_MDPS)) - -/* Gyro normalized FS value from Full Scale register */ -#define LSM6DSM_GYRO_NORMALIZE_FS(_reg) \ - ((LSM6DSM_GYRO_FS_MIN_VAL_MDPS << (_reg)) / 1000) - -/* FS register address/mask for Acc/Gyro sensors */ -#define LSM6DSM_RANGE_REG(_sensor) (LSM6DSM_ACCEL_FS_ADDR + (_sensor)) -#define LSM6DSM_RANGE_MASK 0x0c - -/* Status register bitmask for Acc/Gyro data ready */ -enum lsm6dsm_status { - LSM6DSM_STS_DOWN = 0x00, - LSM6DSM_STS_XLDA_UP = 0x01, - LSM6DSM_STS_GDA_UP = 0x02 -}; - -#define LSM6DSM_STS_XLDA_MASK 0x01 -#define LSM6DSM_STS_GDA_MASK 0x02 - -/* Sensor resolution in number of bits: fixed 16 bit */ -#define LSM6DSM_RESOLUTION 16 - -extern const struct accelgyro_drv lsm6dsm_drv; - -void lsm6dsm_interrupt(enum gpio_signal signal); - -struct lsm6dsm_fifo_data { - /* - * FIFO data order is based on the ODR of each sensors. - * For example Acc @ 52 Hz, Gyro @ 26 Hz Mag @ 13 Hz in FIFO we have - * for each pattern this data samples: - * ________ _______ _______ _______ ________ _______ _______ - * | Gyro_0 | Acc_0 | Mag_0 | Acc_1 | Gyro_1 | Acc_2 | Acc_3 | - * |________|_______|_______|_______|________|_______|_______| - * - * Total samples for each pattern: 2 Gyro, 4 Acc, 1 Mag - */ - /* Calculated samples in a pattern, based on ODR. */ - int samples_in_pattern[FIFO_DEV_NUM]; - - /* Sum of all samples_in_pattern. */ - int total_samples_in_pattern; -}; - -/* - * Structure used to maintain the load state per sensor. This will be used to - * properly spread values in case we have more than one reading for a given - * sensor in a single fifo read pass. - */ -struct load_fifo_sensor_state_t { - uint32_t int_timestamp; - uint8_t sample_count; - int sample_rate; -}; - -/** - * Structure used to hold fifo state. This struct should only be used if - * CONFIG_ACCEL_FIFO is defined. - */ -struct lsm6dsm_accel_fifo_state { - struct lsm6dsm_fifo_data config; - struct lsm6dsm_fifo_data current; - int next_in_pattern; - /* - * After an ODR change, the sensor filters need settling time; discard - * initial samples with incorrect values - */ - unsigned int samples_to_discard[FIFO_DEV_NUM]; - struct load_fifo_sensor_state_t load_fifo_sensor_state[FIFO_DEV_NUM]; -}; - -/* - * lsm6dsm_data is used for accel gyro and the sensor connect to a LSM6DSM. - * - * +---- lsm6dsm_data ------------------------------------------------+ - * | +--- stprivate_data ---+ | - * | | | ST common data for accelerometer | - * | +----------------------+ | - * | +--- stprivate_data ---+ | - * | | | ST common data for gyroscope | - * | +----------------------+ | - * | +--- stprivate_data ---+ | - * | | | ST common data for LIS2MDL magnetomer | - * | +----------------------+ (optional) | - * | | - * | Fifo Information | - * | | - * | +----- Magnetometer information -----------------------------+ | - * | | +--- mag_cal_t ------+ | | - * | | | | Data for online calibration | | - * | | +--------------------+ | | - * | | Other privata data | | - * | +------------------------------------------------------------+ | - * +------------------------------------------------------------------+ - * - * In motion_sensors array, use LSM6DSM_ST_DATA to point drv_data - * to the right st_data structure. - */ -struct lsm6dsm_data { -#ifdef CONFIG_MAG_LSM6DSM_LIS2MDL - /* LIS2MDL uses st_mems_common and needs stprivate_data */ - struct stprivate_data st_data[3]; -#else - /* BMM150 doesn't use st_mems_common; no stprivate_data */ - struct stprivate_data st_data[2]; -#endif - struct lsm6dsm_accel_fifo_state *accel_fifo_state; -#if defined(CONFIG_LSM6DSM_SEC_I2C) && defined(CONFIG_MAG_CALIBRATE) - union { -#ifdef CONFIG_MAG_LSM6DSM_BMM150 - struct bmm150_private_data compass; -#endif -#ifdef CONFIG_MAG_LSM6DSM_LIS2MDL - struct lis2mdl_private_data compass; -#endif - struct mag_cal_t cal; - }; -#endif /* CONFIG_MAG_CALIBRATE */ -}; - -#ifdef CONFIG_ACCEL_FIFO -#define LSM6DSM_ACCEL_FIFO_STATE (&((struct lsm6dsm_accel_fifo_state) {})) -#else -#define LSM6DSM_ACCEL_FIFO_STATE NULL -#endif - -#define LSM6DSM_DATA \ - ((struct lsm6dsm_data) { \ - .accel_fifo_state = LSM6DSM_ACCEL_FIFO_STATE, \ - }) - -/* - * Note: The specific number of samples to discard depends on the filters - * configured for the chip, as well as the ODR being set. For most of our - * allowed ODRs, 5 should suffice. - * See: ST's LSM6DSM application notes (AN4987) Tables 17 and 19 for details - */ -#define LSM6DSM_DISCARD_SAMPLES 5 - -#define LSM6DSM_ST_DATA(g, type) (&(&(g))->st_data[(type)]) - -#define LSM6DSM_MAIN_SENSOR(_s) ((_s) - (_s)->type) - -#define LSM6DSM_GET_DATA(_s) \ - ((struct lsm6dsm_data *)(LSM6DSM_MAIN_SENSOR(_s))->drv_data) - -#if defined(CONFIG_LSM6DSM_SEC_I2C) && defined(CONFIG_MAG_CALIBRATE) -#define LIS2MDL_CAL(_s) (&LSM6DSM_GET_DATA(_s)->cal) -#endif - -int lsm6dsm_set_data_rate(const struct motion_sensor_t *s, int rate, int rnd); - - -#endif /* __CROS_EC_ACCELGYRO_LSM6DSM_H */ diff --git a/driver/accelgyro_lsm6dso.c b/driver/accelgyro_lsm6dso.c deleted file mode 100644 index e8ea0794d7..0000000000 --- a/driver/accelgyro_lsm6dso.c +++ /dev/null @@ -1,504 +0,0 @@ -/* Copyright 2019 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. - */ - -/** - * LSM6DSO Accel and Gyro module for Chrome EC - * 3D digital accelerometer & 3D digital gyroscope - * - * For any details on driver implementation please - * Refer to AN5192 Application Note on www.st.com - */ - -#include "driver/accelgyro_lsm6dso.h" -#include "hooks.h" -#include "hwtimer.h" -#include "math_util.h" -#include "motion_sense_fifo.h" -#include "task.h" -#include "timer.h" - -#define CPRINTS(format, args...) cprints(CC_ACCEL, format, ## args) - -STATIC_IF(CONFIG_ACCEL_FIFO) volatile uint32_t last_interrupt_timestamp; - -/* - * When ODR change, the sensor filters need settling time; - * Add a counter to discard a well known number of data with - * incorrect values. - */ -static uint32_t samples_to_discard[LSM6DSO_FIFO_DEV_NUM]; - -/** - * @return output data base register for sensor - */ -static inline int get_xyz_reg(enum motionsensor_type type) -{ - return LSM6DSO_ACCEL_OUT_X_L_ADDR - - (LSM6DSO_ACCEL_OUT_X_L_ADDR - LSM6DSO_GYRO_OUT_X_L_ADDR) * type; -} - -#ifdef CONFIG_ACCEL_INTERRUPTS -/** - * Configure interrupt int 1 to fire handler for: - * - * FIFO threshold on watermark (1 sample) - * - * @s: Motion sensor pointer - */ -static int config_interrupt(const struct motion_sensor_t *s) -{ - int ret = EC_SUCCESS; - int int1_ctrl_val; - - if (!IS_ENABLED(CONFIG_ACCEL_FIFO)) - return ret; - - ret = st_raw_read8(s->port, s->i2c_spi_addr_flags, LSM6DSO_INT1_CTRL, - &int1_ctrl_val); - if (ret != EC_SUCCESS) - return ret; - - /* - * Configure FIFO threshold to 1 sample: interrupt on watermark - * will be generated every time a new data sample will be stored - * in FIFO. The interrupr on watermark is cleared only when the - * number or samples still present in FIFO exceeds the - * configured threshold. - */ - ret = st_raw_write8(s->port, s->i2c_spi_addr_flags, - LSM6DSO_FIFO_CTRL1_ADDR, 1); - if (ret != EC_SUCCESS) - return ret; - - int1_ctrl_val |= LSM6DSO_INT_FIFO_TH | LSM6DSO_INT_FIFO_OVR | - LSM6DSO_INT_FIFO_FULL; - - ret = st_raw_write8(s->port, s->i2c_spi_addr_flags, LSM6DSO_INT1_CTRL, - int1_ctrl_val); - - return ret; -} - -/** - * fifo_disable - set fifo mode to LSM6DSO_FIFO_MODE_BYPASS_VAL - * @s: Motion sensor pointer: must be MOTIONSENSE_TYPE_ACCEL. - */ -static int fifo_disable(const struct motion_sensor_t *s) -{ - return st_raw_write8(s->port, s->i2c_spi_addr_flags, - LSM6DSO_FIFO_CTRL4_ADDR, - LSM6DSO_FIFO_MODE_BYPASS_VAL); -} - -/** - * set_fifo_params - Configure internal FIFO parameters - * - * Configure FIFO decimator to have every time the right pattern - * with acc/gyro - */ -static int fifo_enable(const struct motion_sensor_t *s) -{ - return st_raw_write8(s->port, s->i2c_spi_addr_flags, - LSM6DSO_FIFO_CTRL4_ADDR, - LSM6DSO_FIFO_MODE_CONTINUOUS_VAL); -} - -/** - * push_fifo_data - Scan data pattern and push upside - */ -static void push_fifo_data(struct motion_sensor_t *main_s, uint8_t *fifo, - uint32_t saved_ts) -{ - struct ec_response_motion_sensor_data vect; - struct motion_sensor_t *sensor; - uint8_t tag; - int id; - int *axis; - uint8_t *ptr; - uint8_t ag_maps[] = { - MOTIONSENSE_TYPE_GYRO, - MOTIONSENSE_TYPE_ACCEL, - }; - - /* - * FIFO pattern is as follow (i.e. Acc/Gyro @ same ODR) - * ________ ____________ _______ ____________ - * | TAG_XL | Acc[x,y,z] | TAG_G | Gyr[x,y,z] | - * |________|____________|_______|____________| - * |<-------- 1 -------->|<-------- 2 ------->| (FIFO Threshold) - * - * First byte is tag, next data. - * Data pattern len is fixed for each sample. - * FIFO threshold is related to sample data (7 byte). - */ - ptr = fifo + LSM6DSO_TAG_SIZE; - tag = (*fifo >> 3) - LSM6DSO_GYRO_TAG; - id = ag_maps[tag]; - - /* Discard samples every ODR changes. */ - if (samples_to_discard[id] > 0) { - samples_to_discard[id]--; - return; - } - - sensor = main_s + id; - axis = sensor->raw_xyz; - - /* Apply precision, sensitivity and rotation. */ - st_normalize(sensor, axis, ptr); - vect.data[X] = axis[X]; - vect.data[Y] = axis[Y]; - vect.data[Z] = axis[Z]; - - vect.flags = 0; - vect.sensor_num = sensor - motion_sensors; - motion_sense_fifo_stage_data(&vect, sensor, 3, saved_ts); -} - -static inline int load_fifo(struct motion_sensor_t *s, - const struct lsm6dso_fstatus *fsts, - uint32_t saved_ts) -{ - uint8_t fifo[FIFO_READ_LEN], *ptr; - int i, err, read_len = 0, word_len, fifo_len; - uint16_t fifo_depth; - - fifo_depth = fsts->len & LSM6DSO_FIFO_DIFF_MASK; - fifo_len = fifo_depth * LSM6DSO_FIFO_SAMPLE_SIZE; - while (read_len < fifo_len) { - word_len = GENERIC_MIN(fifo_len - read_len, sizeof(fifo)); - err = st_raw_read_n_noinc(s->port, s->i2c_spi_addr_flags, - LSM6DSO_FIFO_DATA_ADDR_TAG, - fifo, word_len); - if (err != EC_SUCCESS) - return err; - - for (i = 0; i < word_len; i += LSM6DSO_FIFO_SAMPLE_SIZE) { - ptr = &fifo[i]; - push_fifo_data(LSM6DSO_MAIN_SENSOR(s), ptr, saved_ts); - } - read_len += word_len; - } - - return read_len; -} - -/** - * accelgyro_config_fifo - update mode and ODR for FIFO decimator - */ -static int accelgyro_config_fifo(const struct motion_sensor_t *s) -{ - int err; - struct stprivate_data *data = LSM6DSO_GET_DATA(s); - uint8_t reg_val; - uint8_t fifo_odr_mask; - - /* Changing in ODR must stop FIFO. */ - err = fifo_disable(s); - if (err != EC_SUCCESS) - return err; - - /* - * If ODR changes restore to default discard samples number - * the counter related to this sensor. - */ - samples_to_discard[s->type] = LSM6DSO_DISCARD_SAMPLES; - - fifo_odr_mask = LSM6DSO_FIFO_ODR_TO_REG(s); - reg_val = LSM6DSO_ODR_TO_REG(data->base.odr); - err = st_write_data_with_mask(s, LSM6DSO_FIFO_CTRL3_ADDR, - fifo_odr_mask, reg_val); - if (err != EC_SUCCESS) - return err; - - return fifo_enable(s); -} - -/** - * lsm6dso_interrupt - interrupt from int1 pin of sensor - */ -void lsm6dso_interrupt(enum gpio_signal signal) -{ - if (IS_ENABLED(CONFIG_ACCEL_FIFO)) - last_interrupt_timestamp = __hw_clock_source_read(); - - task_set_event(TASK_ID_MOTIONSENSE, - CONFIG_ACCEL_LSM6DSO_INT_EVENT, 0); -} - -/** - * irq_handler - bottom half of the interrupt task sheduled by consumer - */ -static int irq_handler(struct motion_sensor_t *s, uint32_t *event) -{ - int ret = EC_SUCCESS; - struct lsm6dso_fstatus fsts; - - if (((s->type != MOTIONSENSE_TYPE_ACCEL) && - (s->type != MOTIONSENSE_TYPE_GYRO)) || - (!(*event & CONFIG_ACCEL_LSM6DSO_INT_EVENT))) - return EC_ERROR_NOT_HANDLED; - - if (IS_ENABLED(CONFIG_ACCEL_FIFO)) { - /* Read how many data patterns on FIFO to read. */ - ret = st_raw_read_n_noinc(s->port, s->i2c_spi_addr_flags, - LSM6DSO_FIFO_STS1_ADDR, - (uint8_t *)&fsts, sizeof(fsts)); - if (ret != EC_SUCCESS) - return ret; - - if (fsts.len & (LSM6DSO_FIFO_DATA_OVR | LSM6DSO_FIFO_FULL)) - CPRINTS("%s FIFO Overrun: %04x", s->name, fsts.len); - - if (fsts.len & LSM6DSO_FIFO_DIFF_MASK) - ret = load_fifo(s, &fsts, last_interrupt_timestamp); - - if (IS_ENABLED(CONFIG_ACCEL_FIFO) && ret > 0) - motion_sense_fifo_commit_data(); - } - - return ret; -} -#endif /* CONFIG_ACCEL_INTERRUPTS */ - -/** - * set_range - set full scale range - * @s: Motion sensor pointer - * @range: Range - * @rnd: Round up/down flag - * Note: Range is sensitivity/gain for speed purpose - */ -static int set_range(const struct motion_sensor_t *s, int range, int rnd) -{ - int err; - uint8_t ctrl_reg, reg_val; - struct stprivate_data *data = LSM6DSO_GET_DATA(s); - int newrange = range; - - ctrl_reg = LSM6DSO_RANGE_REG(s->type); - if (s->type == MOTIONSENSE_TYPE_ACCEL) { - /* Adjust and check rounded value for Acc. */ - if (rnd && (newrange < LSM6DSO_ACCEL_NORMALIZE_FS(newrange))) - newrange *= 2; - - if (newrange > LSM6DSO_ACCEL_FS_MAX_VAL) - newrange = LSM6DSO_ACCEL_FS_MAX_VAL; - - reg_val = lsm6dso_accel_fs_reg(newrange); - } else { - /* Adjust and check rounded value for Gyro. */ - reg_val = LSM6DSO_GYRO_FS_REG(range); - if (rnd && (range > LSM6DSO_GYRO_NORMALIZE_FS(reg_val))) - reg_val++; - - if (reg_val > LSM6DSO_GYRO_FS_MAX_REG_VAL) - reg_val = LSM6DSO_GYRO_FS_MAX_REG_VAL; - - newrange = LSM6DSO_GYRO_NORMALIZE_FS(reg_val); - } - - mutex_lock(s->mutex); - err = st_write_data_with_mask(s, ctrl_reg, LSM6DSO_RANGE_MASK, - reg_val); - if (err == EC_SUCCESS) - data->base.range = newrange; - - mutex_unlock(s->mutex); - - return EC_SUCCESS; -} - -/** - * get_range - get full scale range - * @s: Motion sensor pointer - */ -static int get_range(const struct motion_sensor_t *s) -{ - struct stprivate_data *data = LSM6DSO_GET_DATA(s); - - return data->base.range; -} - -/** - * set_data_rate set sensor data rate - * @s: Motion sensor pointer - * @range: Rate (mHz) - * @rnd: Round up/down flag - */ -static int set_data_rate(const struct motion_sensor_t *s, int rate, int rnd) -{ - int ret, normalized_rate = 0; - struct stprivate_data *data = LSM6DSO_GET_DATA(s); - uint8_t ctrl_reg, reg_val = 0; - - ctrl_reg = LSM6DSO_ODR_REG(s->type); - if (rate > 0) { - reg_val = LSM6DSO_ODR_TO_REG(rate); - normalized_rate = LSM6DSO_REG_TO_ODR(reg_val); - - if (rnd && (normalized_rate < rate)) { - reg_val++; - normalized_rate = LSM6DSO_REG_TO_ODR(reg_val); - } - - if (normalized_rate < LSM6DSO_ODR_MIN_VAL || - normalized_rate > MIN(LSM6DSO_ODR_MAX_VAL, - CONFIG_EC_MAX_SENSOR_FREQ_MILLIHZ)) - return EC_RES_INVALID_PARAM; - } - - mutex_lock(s->mutex); - ret = st_write_data_with_mask(s, ctrl_reg, LSM6DSO_ODR_MASK, reg_val); - if (ret == EC_SUCCESS) { - data->base.odr = normalized_rate; - if (IS_ENABLED(CONFIG_ACCEL_FIFO)) - accelgyro_config_fifo(s); - } - - mutex_unlock(s->mutex); - - return ret; -} - -static int is_data_ready(const struct motion_sensor_t *s, int *ready) -{ - int ret, tmp; - - ret = st_raw_read8(s->port, s->i2c_spi_addr_flags, - LSM6DSO_STATUS_REG, &tmp); - if (ret != EC_SUCCESS) { - CPRINTS("%s type:0x%X RS Error", s->name, s->type); - - return ret; - } - - if (MOTIONSENSE_TYPE_ACCEL == s->type) - *ready = (LSM6DSO_STS_XLDA_UP == (tmp & LSM6DSO_STS_XLDA_MASK)); - else - *ready = (LSM6DSO_STS_GDA_UP == (tmp & LSM6DSO_STS_GDA_MASK)); - - return EC_SUCCESS; -} - -/* - * Is not very efficient to collect the data in read: better have an interrupt - * and collect in FIFO, even if it has one item: we don't have to check if the - * sensor is ready (minimize I2C access). - */ -static int read(const struct motion_sensor_t *s, intv3_t v) -{ - uint8_t raw[OUT_XYZ_SIZE]; - uint8_t xyz_reg; - int ret, tmp = 0; - - ret = is_data_ready(s, &tmp); - if (ret != EC_SUCCESS) - return ret; - - /* - * If sensor data is not ready, return the previous read data. - * Note: return success so that motion senor task can read again - * to get the latest updated sensor data quickly. - */ - if (!tmp) { - if (v != s->raw_xyz) - memcpy(v, s->raw_xyz, sizeof(s->raw_xyz)); - - return EC_SUCCESS; - } - - xyz_reg = get_xyz_reg(s->type); - - /* Read data bytes starting at xyz_reg. */ - ret = st_raw_read_n_noinc(s->port, s->i2c_spi_addr_flags, - xyz_reg, raw, OUT_XYZ_SIZE); - if (ret != EC_SUCCESS) - return ret; - - /* Apply precision, sensitivity and rotation vector. */ - st_normalize(s, v, raw); - - return EC_SUCCESS; -} - -static int init(const struct motion_sensor_t *s) -{ - int ret = 0, tmp; - struct stprivate_data *data = LSM6DSO_GET_DATA(s); - - ret = st_raw_read8(s->port, s->i2c_spi_addr_flags, - LSM6DSO_WHO_AM_I_REG, &tmp); - if (ret != EC_SUCCESS) - return EC_ERROR_UNKNOWN; - - if (tmp != LSM6DSO_WHO_AM_I) - return EC_ERROR_ACCESS_DENIED; - - /* - * This sensor can be powered through an EC reboot, so the state of the - * sensor is unknown here so reset it - * LSM6DSO supports both Acc & Gyro features - * Board will see two virtual sensor devices: Acc & Gyro - * Requirement: Acc need be init before Gyro - */ - if (s->type == MOTIONSENSE_TYPE_ACCEL) { - mutex_lock(s->mutex); - - /* Software reset. */ - ret = st_raw_write8(s->port, s->i2c_spi_addr_flags, - LSM6DSO_CTRL3_ADDR, LSM6DSO_SW_RESET); - if (ret != EC_SUCCESS) - goto err_unlock; - - /* - * Output data not updated until have been read. - * Prefer interrupt to be active low. - */ - ret = st_raw_write8(s->port, s->i2c_spi_addr_flags, - LSM6DSO_CTRL3_ADDR, - LSM6DSO_BDU | LSM6DSO_IF_INC); - if (ret != EC_SUCCESS) - goto err_unlock; - - if (IS_ENABLED(CONFIG_ACCEL_FIFO)) { - ret = fifo_disable(s); - if (ret != EC_SUCCESS) - goto err_unlock; - } - -#ifdef CONFIG_ACCEL_INTERRUPTS - ret = config_interrupt(s); - if (ret != EC_SUCCESS) - goto err_unlock; -#endif /* CONFIG_ACCEL_INTERRUPTS */ - - mutex_unlock(s->mutex); - } - - /* Set default resolution common to Acc and Gyro. */ - data->resol = LSM6DSO_RESOLUTION; - return sensor_init_done(s); - -err_unlock: - mutex_unlock(s->mutex); - CPRINTS("%s: MS Init type:0x%X Error", s->name, s->type); - - return ret; -} - -const struct accelgyro_drv lsm6dso_drv = { - .init = init, - .read = read, - .set_range = set_range, - .get_range = get_range, - .get_resolution = st_get_resolution, - .set_data_rate = set_data_rate, - .get_data_rate = st_get_data_rate, - .set_offset = st_set_offset, - .get_offset = st_get_offset, -#ifdef CONFIG_ACCEL_INTERRUPTS - .irq_handler = irq_handler, -#endif /* CONFIG_ACCEL_INTERRUPTS */ -}; diff --git a/driver/accelgyro_lsm6dso.h b/driver/accelgyro_lsm6dso.h deleted file mode 100644 index a823fe7e61..0000000000 --- a/driver/accelgyro_lsm6dso.h +++ /dev/null @@ -1,231 +0,0 @@ -/* Copyright 2019 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. - */ - -/* LSM6DSO Accel and Gyro driver for Chrome EC */ - -#ifndef __CROS_EC_ACCELGYRO_LSM6DSO_H -#define __CROS_EC_ACCELGYRO_LSM6DSO_H - -#include "stm_mems_common.h" - -/* - * 7-bit address is 110101xb. Where 'x' is determined - * by the voltage on the ADDR pin - */ -#define LSM6DSO_ADDR0_FLAGS 0x6a -#define LSM6DSO_ADDR1_FLAGS 0x6b - -/* Access to embedded sensor hub register bank */ -#define LSM6DSO_FUNC_CFG_ACC_ADDR 0x01 -#define LSM6DSO_FUNC_CFG_EN 0x80 - -/* Who Am I */ -#define LSM6DSO_WHO_AM_I_REG 0x0f -#define LSM6DSO_WHO_AM_I 0x6c - -/* Common defines for Acc and Gyro sensors */ -#define LSM6DSO_EN_BIT 0x01 -#define LSM6DSO_DIS_BIT 0x00 - -#define LSM6DSO_GYRO_OUT_X_L_ADDR 0x22 -#define LSM6DSO_ACCEL_OUT_X_L_ADDR 0x28 - -#define LSM6DSO_CTRL1_ADDR 0x10 -#define LSM6DSO_CTRL2_ADDR 0x11 -#define LSM6DSO_CTRL3_ADDR 0x12 -#define LSM6DSO_SW_RESET 0x01 -#define LSM6DSO_IF_INC 0x04 -#define LSM6DSO_PP_OD 0x10 -#define LSM6DSO_H_L_ACTIVE 0x20 -#define LSM6DSO_BDU 0x40 - -#define LSM6DSO_CTRL4_ADDR 0x13 -#define LSM6DSO_INT2_ON_INT1_MASK 0x20 - -#define LSM6DSO_CTRL5_ADDR 0x14 -#define LSM6DSO_CTRL6_ADDR 0x15 -#define LSM6DSO_CTRL7_ADDR 0x16 -#define LSM6DSO_CTRL8_ADDR 0x17 -#define LSM6DSO_CTRL9_ADDR 0x18 - -#define LSM6DSO_CTRL10_ADDR 0x19 -#define LSM6DSO_TIMESTAMP_EN 0x20 - -#define LSM6DSO_STATUS_REG 0x1e - -/* Output data rate registers and masks */ -#define LSM6DSO_ODR_REG(_sensor) \ - (LSM6DSO_CTRL1_ADDR + (_sensor)) -#define LSM6DSO_ODR_MASK 0xf0 - -/* Hardware FIFO size in byte */ -#define LSM6DSO_MAX_FIFO_SIZE 4096 -#define LSM6DSO_MAX_FIFO_LENGTH (LSM6DSO_MAX_FIFO_SIZE / OUT_XYZ_SIZE) - -/* FIFO decimator registers and bitmask */ -#define LSM6DSO_FIFO_CTRL1_ADDR 0x07 -#define LSM6DSO_FIFO_CTRL2_ADDR 0x08 - -#define LSM6DSO_FIFO_CTRL3_ADDR 0x09 -#define LSM6DSO_FIFO_ODR_XL_MASK 0x0f -#define LSM6DSO_FIFO_ODR_G_MASK 0xf0 - -#define LSM6DSO_FIFO_CTRL4_ADDR 0x0a -#define LSM6DSO_FIFO_MODE_MASK 0x07 - -#define LSM6DSO_INT1_CTRL 0x0d -#define LSM6DSO_INT2_CTRL 0x0e -#define LSM6DSO_INT_FIFO_TH 0x08 -#define LSM6DSO_INT_FIFO_OVR 0x10 -#define LSM6DSO_INT_FIFO_FULL 0x20 - -#define LSM6DSO_FIFO_STS1_ADDR 0x3a -#define LSM6DSO_FIFO_STS2_ADDR 0x3b -#define LSM6DSO_FIFO_DIFF_MASK 0x07ff -#define LSM6DSO_FIFO_FULL 0x2000 -#define LSM6DSO_FIFO_DATA_OVR 0x4000 -#define LSM6DSO_FIFO_WATERMARK 0x8000 - -/* Out FIFO data register */ -#define LSM6DSO_FIFO_DATA_ADDR_TAG 0x78 - -/* Registers value for supported FIFO mode */ -#define LSM6DSO_FIFO_MODE_BYPASS_VAL 0x00 -#define LSM6DSO_FIFO_MODE_CONTINUOUS_VAL 0x06 - -/* Define device available in FIFO pattern */ -enum lsm6dso_dev_fifo { - LSM6DSO_FIFO_DEV_INVALID = -1, - LSM6DSO_FIFO_DEV_GYRO = 0, - LSM6DSO_FIFO_DEV_ACCEL, - LSM6DSO_FIFO_DEV_NUM, -}; - -/* Define FIFO data pattern, tag and len */ -#define LSM6DSO_SAMPLE_SIZE 6 -#define LSM6DSO_TS_SAMPLE_SIZE 4 -#define LSM6DSO_TAG_SIZE 1 -#define LSM6DSO_FIFO_SAMPLE_SIZE LSM6DSO_SAMPLE_SIZE + LSM6DSO_TAG_SIZE -#define LSM6DSO_MAX_FIFO_DEPTH 416 - -enum lsm6dso_tag_fifo { - LSM6DSO_GYRO_TAG = 0x01, - LSM6DSO_ACC_TAG = 0x02, -}; - -struct lsm6dso_fstatus { - uint16_t len; - uint16_t pattern; -}; - -/* Absolute maximum rate for Acc and Gyro sensors */ -#define LSM6DSO_ODR_MIN_VAL 13000 -#define LSM6DSO_ODR_MAX_VAL \ - MOTION_MAX_SENSOR_FREQUENCY(416000, 13000) - -/* ODR reg value from selected data rate in mHz */ -#define LSM6DSO_ODR_TO_REG(_odr) (__fls(_odr / LSM6DSO_ODR_MIN_VAL) + 1) - -#define LSM6DSO_FIFO_ODR_TO_REG(_s) \ - (_s->type == MOTIONSENSE_TYPE_ACCEL ? LSM6DSO_FIFO_ODR_XL_MASK : \ - LSM6DSO_FIFO_ODR_G_MASK) - -/* Normalized ODR values from selected data rate in mHz */ -#define LSM6DSO_REG_TO_ODR(_reg) (LSM6DSO_ODR_MIN_VAL << (_reg - 1)) - -/* Full Scale ranges value and gain for Acc */ -#define LSM6DSO_FS_LIST_NUM 4 - -#define LSM6DSO_ACCEL_FS_ADDR 0x10 -#define LSM6DSO_ACCEL_FS_MASK 0x0c - -#define LSM6DSO_ACCEL_FS_2G_VAL 0x00 -#define LSM6DSO_ACCEL_FS_4G_VAL 0x02 -#define LSM6DSO_ACCEL_FS_8G_VAL 0x03 -#define LSM6DSO_ACCEL_FS_16G_VAL 0x01 - -#define LSM6DSO_ACCEL_FS_MAX_VAL 16 - -/* Accel reg value from Full Scale range */ -static inline uint8_t lsm6dso_accel_fs_reg(int fs) -{ - uint8_t ret; - - switch(fs) { - case 2: - ret = LSM6DSO_ACCEL_FS_2G_VAL; - break; - case 16: - ret = LSM6DSO_ACCEL_FS_16G_VAL; - break; - default: - ret = __fls(fs); - break; - } - - return ret; -} - -/* Accel normalized FS value from Full Scale */ -#define LSM6DSO_ACCEL_NORMALIZE_FS(_fs) (1 << __fls(_fs)) - -/* Full Scale range value and gain for Gyro */ -#define LSM6DSO_GYRO_FS_ADDR 0x11 -#define LSM6DSO_GYRO_FS_MASK 0x0c - -/* Minimal Gyro range in mDPS */ -#define LSM6DSO_GYRO_FS_MIN_VAL_MDPS ((8750 << 15) / 1000) -#define LSM6DSO_GYRO_FS_MAX_REG_VAL 3 - -/* Gyro reg value for Full Scale selection in DPS */ -#define LSM6DSO_GYRO_FS_REG(_fs) \ - __fls(MAX(1, (_fs * 1000) / LSM6DSO_GYRO_FS_MIN_VAL_MDPS)) - -/* Gyro normalized FS value (in DPS) from Full Scale register */ -#define LSM6DSO_GYRO_NORMALIZE_FS(_reg) \ - ((LSM6DSO_GYRO_FS_MIN_VAL_MDPS << (_reg)) / 1000) - -/* FS register address/mask for Acc/Gyro sensors */ -#define LSM6DSO_RANGE_REG(_sensor) (LSM6DSO_ACCEL_FS_ADDR + (_sensor)) -#define LSM6DSO_RANGE_MASK 0x0c - -/* Status register bit for Acc/Gyro data ready */ -enum lsm6dso_status { - LSM6DSO_STS_DOWN = 0x00, - LSM6DSO_STS_XLDA_UP = 0x01, - LSM6DSO_STS_GDA_UP = 0x02 -}; - -/* Status register bitmask for Acc/Gyro data ready */ -#define LSM6DSO_STS_XLDA_MASK 0x01 -#define LSM6DSO_STS_GDA_MASK 0x02 - -/* Sensor resolution in number of bits: fixed 16 bit */ -#define LSM6DSO_RESOLUTION 16 - -/* Aggregate private data for all supported sensor (Acc, Gyro) */ -struct lsm6dso_data { - struct stprivate_data st_data[LSM6DSO_FIFO_DEV_NUM]; -}; - -/* - * Note: The specific number of samples to discard depends on the filters - * configured for the chip, as well as the ODR being set. For most of our - * allowed ODRs, 3 should suffice. - * See: ST's LSM6DSO application notes (AN5192) Tables 12 and 18 for details - */ -#define LSM6DSO_DISCARD_SAMPLES 3 - -#define LSM6DSO_GET_DATA(_s) ((struct stprivate_data *)((_s)->drv_data)) - -/* Macro to initialize motion_sensors structure */ -#define LSM6DSO_ST_DATA(g, type) (&(&(g))->st_data[(type)]) -#define LSM6DSO_MAIN_SENSOR(_s) ((_s) - (_s)->type) - -extern const struct accelgyro_drv lsm6dso_drv; - -void lsm6dso_interrupt(enum gpio_signal signal); - -#endif /* __CROS_EC_ACCELGYRO_LSM6DSO_H */ diff --git a/driver/als_al3010.c b/driver/als_al3010.c deleted file mode 100644 index b129dc2f57..0000000000 --- a/driver/als_al3010.c +++ /dev/null @@ -1,49 +0,0 @@ -/* 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. - * - * Dyna-Image AL3010 light sensor driver - */ - -#include "driver/als_al3010.h" -#include "i2c.h" - -/** - * Initialise AL3010 light sensor. - */ -int al3010_init(void) -{ - int ret; - - ret = i2c_write8(I2C_PORT_ALS, AL3010_I2C_ADDR, - AL3010_REG_CONFIG, AL3010_GAIN << 4); - if (ret) - return ret; - - return i2c_write8(I2C_PORT_ALS, AL3010_I2C_ADDR, - AL3010_REG_SYSTEM, AL3010_ENABLE); -} - -/** - * Read AL3010 light sensor data. - */ -int al3010_read_lux(int *lux, int af) -{ - int ret; - int val; - long long val64; - - ret = i2c_read16(I2C_PORT_ALS, AL3010_I2C_ADDR, - AL3010_REG_DATA_LOW, &val); - - if (ret) - return ret; - - val64 = val; - val64 = (val64 * AL3010_GAIN_SCALE) / 10000; - val = val64 * af / 100; - - *lux = val; - - return EC_SUCCESS; -} diff --git a/driver/als_al3010.h b/driver/als_al3010.h deleted file mode 100644 index 288e255990..0000000000 --- a/driver/als_al3010.h +++ /dev/null @@ -1,40 +0,0 @@ -/* 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. - * - * Dyna-Image AL3010 light sensor driver - */ - -#ifndef __CROS_EC_ALS_AL3010_H -#define __CROS_EC_ALS_AL3010_H - -/* I2C interface */ -#define AL3010_I2C_ADDR1_FLAGS 0x1C -#define AL3010_I2C_ADDR2_FLAGS 0x1D -#define AL3010_I2C_ADDR3_FLAGS 0x1E - -/* AL3010 registers */ -#define AL3010_REG_SYSTEM 0x00 -#define AL3010_REG_INT_STATUS 0x01 -#define AL3010_REG_CONFIG 0x10 -#define AL3010_REG_DATA_LOW 0x0C - -#define AL3010_ENABLE 0x01 -#define AL3010_GAIN_SELECT 3 - -#define AL3010_GAIN_1 0 /* 77806 lx */ -#define AL3010_GAIN_2 1 /* 19452 lx */ -#define AL3010_GAIN_3 2 /* 4863 lx */ -#define AL3010_GAIN_4 3 /* 1216 lx */ -#define AL3010_GAIN CONCAT2(AL3010_GAIN_, AL3010_GAIN_SELECT) - -#define AL3010_GAIN_SCALE_1 11872 /* 1.1872 lux/count */ -#define AL3010_GAIN_SCALE_2 2968 /* 0.2968 lux/count */ -#define AL3010_GAIN_SCALE_3 742 /* 0.0742 lux/count */ -#define AL3010_GAIN_SCALE_4 186 /* 0.0186 lux/count */ -#define AL3010_GAIN_SCALE CONCAT2(AL3010_GAIN_SCALE_, AL3010_GAIN_SELECT) - -int al3010_init(void); -int al3010_read_lux(int *lux, int af); - -#endif /* __CROS_EC_ALS_AL3010_H */ diff --git a/driver/als_bh1730.c b/driver/als_bh1730.c deleted file mode 100644 index 872fdaa012..0000000000 --- a/driver/als_bh1730.c +++ /dev/null @@ -1,181 +0,0 @@ -/* Copyright 2017 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. - * - * Rohm BH1730 Ambient light sensor driver - */ - -#include "accelgyro.h" -#include "config.h" -#include "console.h" -#include "driver/als_bh1730.h" -#include "i2c.h" - -#define CPRINTS(format, args...) cprints(CC_MOTION_SENSE, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_MOTION_SENSE, format, ## args) - -/** - * Convert BH1730 data0, data1 to lux - */ -static int bh1730_convert_to_lux(uint32_t data0_1) -{ - int lux; - uint16_t data0 = 0x0000ffff & data0_1; - uint16_t data1 = data0_1 >> 16; - uint32_t d0_1k = data0 * 1000; - uint32_t d1_1k = data1 * 1000; - uint32_t d_temp; - uint32_t d_lux; - - if (data0 == 0) - return 0; - else - d_temp = d1_1k / data0; - - if(d_temp < BH1730_LUXTH1_1K) { - d0_1k = BH1730_LUXTH1_D0_1K * data0; - d1_1k = BH1730_LUXTH1_D1_1K * data1; - } else if(d_temp < BH1730_LUXTH2_1K) { - d0_1k = BH1730_LUXTH2_D0_1K * data0; - d1_1k = BH1730_LUXTH2_D1_1K * data1; - } else if(d_temp < BH1730_LUXTH3_1K) { - d0_1k = BH1730_LUXTH3_D0_1K * data0; - d1_1k = BH1730_LUXTH3_D1_1K * data1; - } else if(d_temp < BH1730_LUXTH4_1K) { - d0_1k = BH1730_LUXTH4_D0_1K * data0; - d1_1k = BH1730_LUXTH4_D1_1K * data1; - } else - return 0; - - d_lux = (d0_1k - d1_1k) / BH1730_GAIN_DIV; - d_lux *= 100; - lux = d_lux / ITIME_MS_X_1K; - - return lux; -} - -/** - * Read BH1730 light sensor data. - */ -static int bh1730_read_lux(const struct motion_sensor_t *s, intv3_t v) -{ - struct bh1730_drv_data_t *drv_data = BH1730_GET_DATA(s); - int ret; - int data0_1; - - /* read data0 and data1 from sensor */ - ret = i2c_read32(s->port, s->i2c_spi_addr_flags, - BH1730_DATA0LOW, &data0_1); - if (ret != EC_SUCCESS) { - CPRINTF("bh1730_read_lux - fail %d\n", ret); - return ret; - } - - /* convert sensor data0 and data1 to lux */ - v[0] = bh1730_convert_to_lux(data0_1); - 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 bh1730_set_range(const struct motion_sensor_t *s, int range, - int rnd) -{ - return EC_SUCCESS; -} - -static int bh1730_get_range(const struct motion_sensor_t *s) -{ - return 1; -} - -static int bh1730_set_data_rate(const struct motion_sensor_t *s, - int rate, int roundup) -{ - struct bh1730_drv_data_t *drv_data = BH1730_GET_DATA(s); - - /* now only one rate supported */ - drv_data->rate = BH1730_10000_MHZ; - - return EC_SUCCESS; -} - -static int bh1730_get_data_rate(const struct motion_sensor_t *s) -{ - struct bh1730_drv_data_t *drv_data = BH1730_GET_DATA(s); - - return drv_data->rate; -} - -static int bh1730_set_offset(const struct motion_sensor_t *s, - const int16_t *offset, - int16_t temp) -{ - return EC_SUCCESS; -} - -static int bh1730_get_offset(const struct motion_sensor_t *s, - int16_t *offset, - int16_t *temp) -{ - *offset = 0; - - return EC_SUCCESS; -} - -/** - * Initialise BH1730 Ambient light sensor. - */ -static int bh1730_init(const struct motion_sensor_t *s) -{ - int ret; - - /* power and measurement bit high */ - ret = i2c_write8(s->port, s->i2c_spi_addr_flags, - BH1730_CONTROL, - BH1730_CONTROL_POWER_ENABLE - | BH1730_CONTROL_ADC_EN_ENABLE); - - if (ret != EC_SUCCESS) { - CPRINTF("bh1730_init_sensor - enable fail %d\n", ret); - return ret; - } - - /* set timing */ - ret = i2c_write8(s->port, s->i2c_spi_addr_flags, - BH1730_TIMING, BH1730_CONF_ITIME); - if (ret != EC_SUCCESS) { - CPRINTF("bh1730_init_sensor - time fail %d\n", ret); - return ret; - } - /* set ADC gain */ - ret = i2c_write8(s->port, s->i2c_spi_addr_flags, - BH1730_GAIN, BH1730_CONF_GAIN); - - if (ret != EC_SUCCESS) { - CPRINTF("bh1730_init_sensor - gain fail %d\n", ret); - return ret; - } - - return sensor_init_done(s); -} - -const struct accelgyro_drv bh1730_drv = { - .init = bh1730_init, - .read = bh1730_read_lux, - .set_range = bh1730_set_range, - .get_range = bh1730_get_range, - .set_offset = bh1730_set_offset, - .get_offset = bh1730_get_offset, - .set_data_rate = bh1730_set_data_rate, - .get_data_rate = bh1730_get_data_rate, -}; - diff --git a/driver/als_bh1730.h b/driver/als_bh1730.h deleted file mode 100644 index d0205033e4..0000000000 --- a/driver/als_bh1730.h +++ /dev/null @@ -1,91 +0,0 @@ -/* Copyright 2017 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. - * - * Rohm BH1730 Ambient light sensor driver - */ - -#ifndef __CROS_EC_ALS_BH1730_H -#define __CROS_EC_ALS_BH1730_H - -/* I2C interface */ -#define BH1730_I2C_ADDR_FLAGS 0x29 - -/* BH1730 registers */ -#define BH1730_CONTROL 0x80 -#define BH1730_TIMING 0x81 -#define BH1730_INTERRUPT 0x82 -#define BH1730_THLLOW 0x83 -#define BH1730_THLHIGH 0x84 -#define BH1730_THHLOW 0x85 -#define BH1730_THHHIGH 0x86 -#define BH1730_GAIN 0x87 -#define BH1730_OPART_ID 0x92 -#define BH1730_DATA0LOW 0x94 -#define BH1730_DATA0HIGH 0x95 -#define BH1730_DATA1LOW 0x96 -#define BH1730_DATA1HIGH 0x97 -/* Software reset */ -#define BH1730_RESET 0xE4 - -/* Registers bits */ -#define BH1730_CONTROL_ADC_INTR_INACTIVE (0x00 << 5) -#define BH1730_CONTROL_ADC_INTR_ACTIVE (0x01 << 5) -#define BH1730_CONTROL_ADC_VALID (0x01 << 4) -#define BH1730_CONTROL_ONE_TIME_CONTINOUS (0x00 << 3) -#define BH1730_CONTROL_ONE_TIME_ONETIME (0x01 << 3) -#define BH1730_CONTROL_DATA_SEL_TYPE0_AND_1 (0x00 << 2) -#define BH1730_CONTROL_DATA_SEL_TYPE0 (0x01 << 2) -#define BH1730_CONTROL_ADC_EN_DISABLE (0x00 << 1) -#define BH1730_CONTROL_ADC_EN_ENABLE (0x01 << 1) -#define BH1730_CONTROL_POWER_DISABLE (0x00 << 0) -#define BH1730_CONTROL_POWER_ENABLE (0x01 << 0) - -#define BH1730_GAIN_GAIN_X1_GAIN (0x00 << 0) -#define BH1730_GAIN_GAIN_X2_GAIN (0x01 << 0) -#define BH1730_GAIN_GAIN_X64_GAIN (0x02 << 0) -#define BH1730_GAIN_GAIN_X128_GAIN (0x03 << 0) - -/* Sensor configuration */ -/* Select Gain */ -#define BH1730_CONF_GAIN BH1730_GAIN_GAIN_X64_GAIN -#define BH1730_GAIN_DIV 64 - -/* Select Itime, 0xDA is 102.6ms = 38*2.7ms */ -#define BH1730_CONF_ITIME 0xDA -#define ITIME_MS_X_10 ((256 - BH1730_CONF_ITIME) * 27) -#define ITIME_MS_X_1K (ITIME_MS_X_10*100) - -/* default Itime is about 10Hz */ -#define BH1730_10000_MHZ (10*1000) - -/* - * Use default lux calculation formula parameters if board specific - * parameters are not defined. - */ -#ifndef CONFIG_ALS_BH1730_LUXTH_PARAMS -#define BH1730_LUXTH1_1K 260 -#define BH1730_LUXTH1_D0_1K 1290 -#define BH1730_LUXTH1_D1_1K 2733 -#define BH1730_LUXTH2_1K 550 -#define BH1730_LUXTH2_D0_1K 797 -#define BH1730_LUXTH2_D1_1K 859 -#define BH1730_LUXTH3_1K 1090 -#define BH1730_LUXTH3_D0_1K 510 -#define BH1730_LUXTH3_D1_1K 345 -#define BH1730_LUXTH4_1K 2130 -#define BH1730_LUXTH4_D0_1K 276 -#define BH1730_LUXTH4_D1_1K 130 -#endif - -#define BH1730_GET_DATA(_s) ((struct bh1730_drv_data_t *)(_s)->drv_data) - -struct bh1730_drv_data_t { - int rate; - int last_value; -}; - -extern const struct accelgyro_drv bh1730_drv; - -#endif /* __CROS_EC_ALS_BH1730_H */ - diff --git a/driver/als_isl29035.c b/driver/als_isl29035.c deleted file mode 100644 index db77a19f09..0000000000 --- a/driver/als_isl29035.c +++ /dev/null @@ -1,73 +0,0 @@ -/* Copyright 2013 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. - * - * Intersil ILS29035 light sensor driver - */ - -#include "driver/als_isl29035.h" -#include "i2c.h" - -/* I2C interface */ -#define ILS29035_I2C_ADDR_FLAGS 0x44 -#define ILS29035_REG_COMMAND_I 0 -#define ILS29035_REG_COMMAND_II 1 -#define ILS29035_REG_DATA_LSB 2 -#define ILS29035_REG_DATA_MSB 3 -#define ILS29035_REG_INT_LT_LSB 4 -#define ILS29035_REG_INT_LT_MSB 5 -#define ILS29035_REG_INT_HT_LSB 6 -#define ILS29035_REG_INT_HT_MSB 7 -#define ILS29035_REG_ID 15 - -int isl29035_init(void) -{ - /* - * Tell it to read continually. This uses 70uA, as opposed to nearly - * zero, but it makes the hook/update code cleaner (we don't want to - * wait 90ms to read on demand while processing hook callbacks). - */ - return i2c_write8(I2C_PORT_ALS, ILS29035_I2C_ADDR_FLAGS, - ILS29035_REG_COMMAND_I, 0xa0); -} - -int isl29035_read_lux(int *lux, int af) -{ - int rv, lsb, msb, data; - - /* - * NOTE: It is necessary to read the LSB first, then the MSB. If you do - * it in the opposite order, the results are not correct. This is - * apparently an undocumented "feature". It's especially noticeable in - * one-shot mode. - */ - - /* Read lsb */ - rv = i2c_read8(I2C_PORT_ALS, ILS29035_I2C_ADDR_FLAGS, - ILS29035_REG_DATA_LSB, &lsb); - if (rv) - return rv; - - /* Read msb */ - rv = i2c_read8(I2C_PORT_ALS, ILS29035_I2C_ADDR_FLAGS, - ILS29035_REG_DATA_MSB, &msb); - if (rv) - return rv; - - data = (msb << 8) | lsb; - - /* - * The default power-on values will give 16 bits of precision: - * 0x0000-0xffff indicates 0-1000 lux. We multiply the sensor value by - * a scaling factor to account for attentuation by glass, tinting, etc. - * - * Caution: Don't go nuts with the attentuation factor. If it's - * greater than 32, the signed int math will roll over and you'll get - * very wrong results. Of course, if you have that much attenuation and - * are still getting useful readings, you probably have your sensor - * pointed directly into the sun. - */ - *lux = data * af * 1000 / 0xffff; - - return EC_SUCCESS; -} diff --git a/driver/als_isl29035.h b/driver/als_isl29035.h deleted file mode 100644 index 153ba148f9..0000000000 --- a/driver/als_isl29035.h +++ /dev/null @@ -1,14 +0,0 @@ -/* Copyright 2013 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. - * - * Intersil ILS29035 light sensor driver - */ - -#ifndef __CROS_EC_ALS_ISL29035_H -#define __CROS_EC_ALS_ISL29035_H - -int isl29035_init(void); -int isl29035_read_lux(int *lux, int af); - -#endif /* __CROS_EC_ALS_ISL29035_H */ diff --git a/driver/als_opt3001.c b/driver/als_opt3001.c deleted file mode 100644 index e6332184c0..0000000000 --- a/driver/als_opt3001.c +++ /dev/null @@ -1,322 +0,0 @@ -/* 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. - * - * TI OPT3001 light sensor driver - */ - -#include "common.h" -#include "driver/als_opt3001.h" -#include "i2c.h" - -#ifdef HAS_TASK_ALS -/** - * Read register from OPT3001 light sensor. - */ -static int opt3001_i2c_read(const int reg, int *data_ptr) -{ - int ret; - - ret = i2c_read16(I2C_PORT_ALS, OPT3001_I2C_ADDR_FLAGS, - 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 reg, int data) -{ - data = ((data << 8) & 0xFF00) | ((data >> 8) & 0x00FF); - return i2c_write16(I2C_PORT_ALS, OPT3001_I2C_ADDR_FLAGS, - reg, data); -} - -/** - * Initialise OPT3001 light sensor. - */ -int opt3001_init(void) -{ - int data; - int ret; - - ret = opt3001_i2c_read(OPT3001_REG_MAN_ID, &data); - if (ret) - return ret; - if (data != OPT3001_MANUFACTURER_ID) - return EC_ERROR_UNKNOWN; - - ret = opt3001_i2c_read(OPT3001_REG_DEV_ID, &data); - if (ret) - return ret; - if (data != OPT3001_DEVICE_ID) - return EC_ERROR_UNKNOWN; - - /* - * [15:12]: 0101b Automatic full scale (1310.40lux, 0.32lux/lsb) - * [11] : 1b Conversion time 800ms - * [10:9] : 10b Continuous Mode of conversion operation - * [4] : 1b Latched window-style comparison operation - */ - return opt3001_i2c_write(OPT3001_REG_CONFIGURE, 0x5C10); -} - -/** - * Read OPT3001 light sensor data. - */ -int opt3001_read_lux(int *lux, int af) -{ - int ret; - int data; - - ret = opt3001_i2c_read(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 - */ - *lux = (1 << ((data & 0xF000) >> 12)) * (data & 0x0FFF) * af / 100; - - return EC_SUCCESS; -} - -#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_dev = &opt3001_i2c_read, - .i2c_write_dev = &opt3001_i2c_write, -}; -#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 uint16_t i2c_addr_flags, - const int reg, int *data_ptr) -{ - int ret; - - ret = i2c_read16(port, i2c_addr_flags, - 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 uint16_t i2c_addr_flags, - const int reg, int data) -{ - data = ((data << 8) & 0xFF00) | ((data >> 8) & 0x00FF); - return i2c_write16(port, i2c_addr_flags, reg, data); -} - -/** - * Read OPT3001 light sensor data. - */ -int opt3001_read_lux(const struct motion_sensor_t *s, intv3_t v) -{ - struct opt3001_drv_data_t *drv_data = OPT3001_GET_DATA(s); - int ret; - int data; - - ret = opt3001_i2c_read(s->port, s->i2c_spi_addr_flags, - OPT3001_REG_RESULT, &data); - if (ret) - return ret; - - /* - * lux = 2EXP[3:0] × R[11:0] / 100 - */ - data = (1 << (data >> 12)) * (data & 0x0FFF); - data += drv_data->offset * 100; - data = data * drv_data->scale + data * drv_data->uscale / 10000; - data /= 100; - - if (data < 0) - data = 1; - - v[0] = data; - 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 { - drv_data->last_value = v[0]; - return EC_SUCCESS; - } -} - -static int opt3001_set_range(const struct motion_sensor_t *s, int range, - int rnd) -{ - struct opt3001_drv_data_t *drv_data = OPT3001_GET_DATA(s); - - drv_data->scale = range >> 16; - drv_data->uscale = range & 0xffff; - 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->scale << 16) | (drv_data->uscale); -} - -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->i2c_spi_addr_flags, - OPT3001_REG_CONFIGURE, ®); - if (rv) - return rv; - - rv = opt3001_i2c_write(s->port, s->i2c_spi_addr_flags, - 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) -{ - struct opt3001_drv_data_t *drv_data = OPT3001_GET_DATA(s); - - drv_data->offset = offset[X]; - return EC_SUCCESS; -} - -static int opt3001_get_offset(const struct motion_sensor_t *s, - int16_t *offset, - int16_t *temp) -{ - struct opt3001_drv_data_t *drv_data = OPT3001_GET_DATA(s); - - offset[X] = drv_data->offset; - offset[Y] = 0; - offset[Z] = 0; - *temp = EC_MOTION_SENSE_INVALID_CALIB_TEMP; - return EC_SUCCESS; -} -/** - * 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->i2c_spi_addr_flags, - 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->i2c_spi_addr_flags, - OPT3001_REG_DEV_ID, &data); - if (ret) - return ret; - if (data != OPT3001_DEVICE_ID) - return EC_ERROR_ACCESS_DENIED; - - /* - * [15-12]: 1100b Automatic full-scale setting mode - * [11] : 1b Conversion time 800ms - * [4] : 1b Latched window-style comparison operation - */ - opt3001_i2c_write(s->port, s->i2c_spi_addr_flags, - OPT3001_REG_CONFIGURE, 0xC810); - - opt3001_set_range(s, s->default_range, 0); - - return EC_SUCCESS; -} - -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 deleted file mode 100644 index 6706734870..0000000000 --- a/driver/als_opt3001.h +++ /dev/null @@ -1,68 +0,0 @@ -/* 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. - * - * TI OPT3001 light sensor driver - */ - -#ifndef __CROS_EC_ALS_OPT3001_H -#define __CROS_EC_ALS_OPT3001_H - -/* I2C interface */ -#define OPT3001_I2C_ADDR1_FLAGS 0x44 -#define OPT3001_I2C_ADDR2_FLAGS 0x45 -#define OPT3001_I2C_ADDR3_FLAGS 0x46 -#define OPT3001_I2C_ADDR4_FLAGS 0x47 - -/* 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 - -/* OPT3001 register values */ -#define OPT3001_MANUFACTURER_ID 0x5449 -#define OPT3001_DEVICE_ID 0x3001 - -/* Min and Max sampling frequency in mHz */ -#define OPT3001_LIGHT_MIN_FREQ 1250 -#define OPT3001_LIGHT_MAX_FREQ 10000 -#if (CONFIG_EC_MAX_SENSOR_FREQ_MILLIHZ <= OPT3001_LIGHT_MAX_FREQ) -#error "EC too slow for light sensor" -#endif - -#ifdef HAS_TASK_ALS -int opt3001_init(void); -int opt3001_read_lux(int *lux, int af); -#else -#define OPT3001_GET_DATA(_s) ((struct opt3001_drv_data_t *)(_s)->drv_data) - -struct opt3001_drv_data_t { - int rate; - int last_value; - /* the coef is scale.uscale */ - int16_t scale; - uint16_t uscale; - int16_t offset; -}; - -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; -#endif - -#endif /* __CROS_EC_ALS_OPT3001_H */ diff --git a/driver/als_si114x.c b/driver/als_si114x.c deleted file mode 100644 index 35405bbea7..0000000000 --- a/driver/als_si114x.c +++ /dev/null @@ -1,603 +0,0 @@ -/* 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 "hwtimer.h" -#include "i2c.h" -#include "math_util.h" -#include "motion_sense_fifo.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) - -static int init(const struct motion_sensor_t *s); - -/** - * Read 8bit register from device. - */ -static inline int raw_read8(const int port, const uint16_t i2c_addr_flags, - const int reg, int *data_ptr) -{ - return i2c_read8(port, i2c_addr_flags, reg, data_ptr); -} - -/** - * Write 8bit register from device. - */ -static inline int raw_write8(const int port, const uint16_t i2c_addr_flags, - const int reg, int data) -{ - return i2c_write8(port, i2c_addr_flags, reg, data); -} - -/** - * Read 16bit register from device. - */ -static inline int raw_read16(const int port, const uint16_t i2c_addr_flags, - const int reg, int *data_ptr) -{ - return i2c_read16(port, i2c_addr_flags, 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->port, s->i2c_spi_addr_flags, - SI114X_REG_PARAM_WR, *value); - if (ret != EC_SUCCESS) - goto error; - } - - ret = raw_write8(s->port, s->i2c_spi_addr_flags, - SI114X_REG_COMMAND, op | (param & 0x1F)); - if (ret != EC_SUCCESS) - goto error; - - ret = raw_read8(s->port, s->i2c_spi_addr_flags, - 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_drv_data_t *data = SI114X_GET_DATA(s); - struct si114x_typed_data_t *type_data = SI114X_GET_TYPED_DATA(s); - - /* Read ALX result */ - for (i = 0; i < nb; i++) { - ret = raw_read16(s->port, s->i2c_spi_addr_flags, - type_data->base_data_reg + i * 2, - &val); - if (ret) - break; - if (val == SI114X_OVERFLOW) { - /* overflowing, try next time. */ - return EC_SUCCESS; - } else if (val + type_data->offset <= 0) { - /* No light */ - val = 1; - } else { - /* Add offset, calibration */ - val += type_data->offset; - } - /* - * Proximity sensor data is inverse of the distance. - * Return back something proportional to distance, - * we correct later with the scale parameter. - */ - if (s->type == MOTIONSENSE_TYPE_PROX) - val = SI114X_PS_INVERSION(val); - val = val * type_data->scale + - val * type_data->uscale / 10000; - s->raw_xyz[i] = val; - } - - if (ret != EC_SUCCESS) - return ret; - - if (s->type == MOTIONSENSE_TYPE_PROX) - data->covered = (s->raw_xyz[0] < SI114X_COVERED_THRESHOLD); - else if (data->covered) - /* - * The sensor (proximity & light) is covered. The light data - * will most likely be incorrect (darker than expected), so - * ignore the measurement. - */ - return EC_SUCCESS; - - /* 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_ERROR_UNCHANGED; - - if (IS_ENABLED(CONFIG_ACCEL_FIFO)) { - struct ec_response_motion_sensor_data vector; - - 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; - vector.sensor_num = s - motion_sensors; - motion_sense_fifo_stage_data(&vector, s, nb, - __hw_clock_source_read()); - motion_sense_fifo_commit_data(); - /* - * TODO: get time at a more accurate spot. - * Like in si114x_interrupt - */ - } - /* Otherwise, we need to copy raw_xyz into xyz with mutex */ - return EC_SUCCESS; -} - -void si114x_interrupt(enum gpio_signal signal) -{ - task_set_event(TASK_ID_MOTIONSENSE, - CONFIG_ALS_SI114X_INT_EVENT, 0); -} - -#ifdef CONFIG_ALS_SI114X_POLLING -static void si114x_read_deferred(void) -{ - task_set_event(TASK_ID_MOTIONSENSE, - CONFIG_ALS_SI114X_INT_EVENT, 0); - -} -DECLARE_DEFERRED(si114x_read_deferred); -#endif - -/** - * 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_ERROR_NOT_HANDLED; - - ret = raw_read8(s->port, s->i2c_spi_addr_flags, - SI114X_REG_IRQ_STATUS, &val); - if (ret) - return ret; - - if (!(val & type_data->irq_flags)) - return EC_ERROR_INVAL; - - /* clearing IRQ */ - ret = raw_write8(s->port, s->i2c_spi_addr_flags, - 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->port, s->i2c_spi_addr_flags, - 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->port, s->i2c_spi_addr_flags, - 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, intv3_t v) -{ - int ret = 0; - 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"); - return EC_ERROR_INVAL; - } - ret = raw_write8(s->port, s->i2c_spi_addr_flags, - SI114X_REG_COMMAND, cmd); -#ifdef CONFIG_ALS_SI114X_POLLING - hook_call_deferred(&si114x_read_deferred_data, - SI114x_POLLING_DELAY); -#endif - ret = EC_RES_IN_PROGRESS; - break; - case SI114X_ALS_IN_PROGRESS_PS_PENDING: - case SI114X_PS_IN_PROGRESS_ALS_PENDING: - ret = EC_ERROR_ACCESS_DENIED; - break; - case SI114X_NOT_READY: - ret = EC_ERROR_NOT_POWERED; - } -#if 0 /* This code is incorrect https://crbug.com/956569 */ - if (ret == EC_ERROR_ACCESS_DENIED && - s->type == MOTIONSENSE_TYPE_LIGHT) { - timestamp_t ts_now = get_time(); - - /* - * We were unable to access the sensor for THRES time. - * We should reset the sensor to clear the interrupt register - * and the state machine. - */ - if (time_after(ts_now.le.lo, - s->last_collection + SI114X_DENIED_THRESHOLD)) { - int ret, val; - - ret = raw_read8(s->port, s->addr, - SI114X_REG_IRQ_STATUS, &val); - CPRINTS("%d stuck IRQ_STATUS 0x%02x - ret %d", - s->name, val, ret); - init(s); - } - } -#endif - 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->port, 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->port, s->port, 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->port, s->i2c_spi_addr_flags, - SI114X_REG_COMMAND, SI114X_CMD_RESET); - if (ret != EC_SUCCESS) - return ret; - msleep(20); - - /* hardware key, magic value */ - ret = raw_write8(s->port, s->i2c_spi_addr_flags, - SI114X_REG_HW_KEY, 0x17); - if (ret != EC_SUCCESS) - return ret; - msleep(20); - - /* interrupt configuration, interrupt output enable */ - ret = raw_write8(s->port, s->i2c_spi_addr_flags, - SI114X_REG_INT_CFG, SI114X_INT_CFG_OE); - if (ret != EC_SUCCESS) - return ret; - - /* enable interrupt for certain activities */ - ret = raw_write8(s->port, s->i2c_spi_addr_flags, - 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->port, s->i2c_spi_addr_flags, - SI114X_REG_MEAS_RATE, 0); - if (ret != EC_SUCCESS) - return ret; - - /* measure ALS every time device wakes up */ - ret = raw_write8(s->port, s->i2c_spi_addr_flags, - SI114X_REG_ALS_RATE, 0); - if (ret != EC_SUCCESS) - return ret; - - /* measure proximity every time device wakes up */ - ret = raw_write8(s->port, s->i2c_spi_addr_flags, - 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->port, s->i2c_spi_addr_flags, - SI114X_REG_PS_LED3, 0x0f); - if (ret != EC_SUCCESS) - return ret; - ret = raw_write8(s->port, s->i2c_spi_addr_flags, - SI114X_REG_PS_LED21, 0xff); - break; - case 2: - ret = raw_write8(s->port, s->i2c_spi_addr_flags, - SI114X_REG_PS_LED21, 0xff); - break; - case 1: - ret = raw_write8(s->port, s->i2c_spi_addr_flags, - 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 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 -1; - - return val & 0x07; -} - -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) -{ - struct si114x_typed_data_t *data = SI114X_GET_TYPED_DATA(s); - return (data->scale << 16) | (data->uscale); -} - -static int get_data_rate(const struct motion_sensor_t *s) -{ - /* Sensor in forced mode, rate is used by motion_sense */ - struct si114x_typed_data_t *data = SI114X_GET_TYPED_DATA(s); - return data->rate; -} - -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 init(const struct motion_sensor_t *s) -{ - int ret, resol; - struct si114x_drv_data_t *data = SI114X_GET_DATA(s); - - /* 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; - - data->state = SI114X_IDLE; - resol = 7; - } else { - if (data->state == SI114X_NOT_READY) - return EC_ERROR_ACCESS_DENIED; - resol = 5; - } - - /* - * Sensor is most likely behind a glass. - * Max out the gain to get correct measurement - */ - set_resolution(s, resol, 0); - - return sensor_init_done(s); -} - -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, -#ifdef CONFIG_ACCEL_INTERRUPTS - .irq_handler = irq_handler, -#endif -}; diff --git a/driver/als_si114x.h b/driver/als_si114x.h deleted file mode 100644 index dc5459e8db..0000000000 --- a/driver/als_si114x.h +++ /dev/null @@ -1,266 +0,0 @@ -/* 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_FLAGS 0x5a - -#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_PS_INVERSION(_data) (BIT(16) / (_data)) -#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 - -/* Proximity sensor finds an object within 5 cm, disable light sensor */ -#define SI114X_COVERED_THRESHOLD 5 -#define SI114X_OVERFLOW 0xffff - -/* Time to wait before re-initializing the device if access is denied */ -#define SI114X_DENIED_THRESHOLD (10 * SECOND) - -/* Delay used for deferred callback when polling is enabled */ -#define SI114x_POLLING_DELAY (8 * MSEC) - -/* Min and Max sampling frequency in mHz */ -#define SI114X_PROX_MIN_FREQ 504 -#define SI114X_PROX_MAX_FREQ 50000 -#define SI114X_LIGHT_MIN_FREQ 504 -#define SI114X_LIGHT_MAX_FREQ 50000 -#if (CONFIG_EC_MAX_SENSOR_FREQ_MILLIHZ <= SI114X_PROX_MAX_FREQ) -#error "EC too slow for light sensor" -#endif - -extern const struct accelgyro_drv si114x_drv; - -enum si114x_state { - SI114X_NOT_READY, - 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; - uint8_t covered; - 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]) - -void si114x_interrupt(enum gpio_signal signal); - -#endif /* __CROS_EC_ALS_SI114X_H */ diff --git a/driver/als_tcs3400.c b/driver/als_tcs3400.c deleted file mode 100644 index 80bf837ad7..0000000000 --- a/driver/als_tcs3400.c +++ /dev/null @@ -1,768 +0,0 @@ -/* Copyright 2019 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. - * - * AMS TCS3400 light sensor driver - */ -#include "accelgyro.h" -#include "common.h" -#include "console.h" -#include "driver/als_tcs3400.h" -#include "hooks.h" -#include "hwtimer.h" -#include "i2c.h" -#include "math_util.h" -#include "motion_sense_fifo.h" -#include "task.h" -#include "util.h" - -#define CPRINTS(fmt, args...) cprints(CC_ACCEL, "%s "fmt, __func__, ## args) - -STATIC_IF(CONFIG_ACCEL_FIFO) volatile uint32_t last_interrupt_timestamp; - -#ifdef CONFIG_TCS_USE_LUX_TABLE -/* - * Stores the number of atime increments/decrements needed to change light value - * by 1% of saturation for each gain setting for each predefined LUX range. - * - * Values in array are TCS_ATIME_GAIN_FACTOR (100x) times actual value to allow - * for fractions using integers. - */ -static const uint16_t -range_atime[TCS_MAX_AGAIN - TCS_MIN_AGAIN + 1][TCS_MAX_ATIME_RANGES] = { -{11200, 5600, 5600, 7200, 5500, 4500, 3800, 3800, 3300, 2900, 2575, 2275, 2075}, -{11200, 5100, 2700, 1840, 1400, 1133, 981, 963, 833, 728, 650, 577, 525}, -{250, 1225, 643, 441, 337, 276, 253, 235, 203, 176, 150, 0, 0}, -{790, 261, 163, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }; - -static void -decrement_atime(struct tcs_saturation_t *sat_p, uint16_t cur_lux, int percent) -{ - int atime; - uint16_t steps; - int lux = MIN(cur_lux, TCS_GAIN_TABLE_MAX_LUX); - - steps = percent * range_atime[sat_p->again][lux / 1000] / - TCS_ATIME_GAIN_FACTOR; - atime = MAX(sat_p->atime - steps, TCS_MIN_ATIME); - sat_p->atime = MIN(atime, TCS_MAX_ATIME); -} - -#else - -static void -decrement_atime(struct tcs_saturation_t *sat_p, - uint16_t __attribute__((unused)) cur_lux, - int __attribute__((unused)) percent) -{ - sat_p->atime = MAX(sat_p->atime - TCS_ATIME_DEC_STEP, TCS_MIN_ATIME); -} - -#endif /* CONFIG_TCS_USE_LUX_TABLE */ - -static void increment_atime(struct tcs_saturation_t *sat_p) -{ - sat_p->atime = MIN(sat_p->atime + TCS_ATIME_INC_STEP, TCS_MAX_ATIME); -} - -static inline int tcs3400_i2c_read8(const struct motion_sensor_t *s, - int reg, int *data) -{ - return i2c_read8(s->port, s->i2c_spi_addr_flags, reg, data); -} - -static inline int tcs3400_i2c_write8(const struct motion_sensor_t *s, - int reg, int data) -{ - return i2c_write8(s->port, s->i2c_spi_addr_flags, reg, data); -} - -static void tcs3400_read_deferred(void) -{ - task_set_event(TASK_ID_MOTIONSENSE, CONFIG_ALS_TCS3400_INT_EVENT, 0); -} -DECLARE_DEFERRED(tcs3400_read_deferred); - -/* convert ATIME register to integration time, in microseconds */ -static int tcs3400_get_integration_time(int atime) -{ - return 2780 * (256 - atime); -} - -static int tcs3400_read(const struct motion_sensor_t *s, intv3_t v) -{ - int atime, again; - int ret; - - /* Chip may have been off, make sure to setup important registers */ - if (TCS3400_RGB_DRV_DATA(s+1)->calibration_mode) { - atime = TCS_CALIBRATION_ATIME; - again = TCS_CALIBRATION_AGAIN; - } else { - atime = TCS3400_RGB_DRV_DATA(s+1)->saturation.atime; - again = TCS3400_RGB_DRV_DATA(s+1)->saturation.again; - } - ret = tcs3400_i2c_write8(s, TCS_I2C_ATIME, atime); - if (ret) - return ret; - ret = tcs3400_i2c_write8(s, TCS_I2C_CONTROL, again); - if (ret) - return ret; - - /* Enable power, ADC, and interrupt to start cycle */ - ret = tcs3400_i2c_write8(s, TCS_I2C_ENABLE, TCS3400_MODE_COLLECTING); - if (ret) - return ret; - - if (IS_ENABLED(CONFIG_ALS_TCS3400_EMULATED_IRQ_EVENT)) { - int atime; - - ret = tcs3400_i2c_read8(s, TCS_I2C_ATIME, &atime); - if (ret) - return ret; - - hook_call_deferred(&tcs3400_read_deferred_data, - tcs3400_get_integration_time(atime)); - } - - /* - * If write succeeded, we've started the read process, but can't - * complete it yet until data is ready, so pass back EC_RES_IN_PROGRESS - * to inform upper level that read data process is under way and data - * will be delivered when available. - */ - return EC_RES_IN_PROGRESS; -} - -static int tcs3400_rgb_read(const struct motion_sensor_t *s, intv3_t v) -{ - ccprintf("WARNING: tcs3400_rgb_read() should never be called\n"); - return EC_SUCCESS; -} - -/* - * tcs3400_adjust_sensor_for_saturation() tries to keep CRGB values as - * close to saturation as possible without saturating by implementing - * the following logic: - * - * If any of the R, G, B, or C channels have saturated, then decrease AGAIN. - * If AGAIN is already at its minimum, increase ATIME if not at its max already. - * - * Else if none of the R, G, B, or C channels have saturated, and - * all samples read are less than 90% of saturation, then increase - * AGAIN if it is not already at its maximum, or if it is, decrease - * ATIME if it is not at it's minimum already. - */ -static int -tcs3400_adjust_sensor_for_saturation(struct motion_sensor_t *s, - uint16_t cur_lux, - uint16_t *crgb_data) -{ - struct tcs_saturation_t *sat_p = - &TCS3400_RGB_DRV_DATA(s+1)->saturation; - const uint8_t save_again = sat_p->again; - const uint8_t save_atime = sat_p->atime; - uint16_t max_val = 0; - int ret; - int status = 0; - int percent_left = 0; - - /* Adjust for saturation if needed */ - ret = tcs3400_i2c_read8(s, TCS_I2C_STATUS, &status); - if (ret) - return ret; - - if (!(status & TCS_I2C_STATUS_RGBC_VALID)) - return EC_SUCCESS; - - for (int i = 0; i < CRGB_COUNT; i++) - max_val = MAX(max_val, crgb_data[i]); - - /* Don't process if status isn't valid yet */ - if ((status & TCS_I2C_STATUS_ALS_SATURATED) || - (max_val >= TCS_SATURATION_LEVEL)) { - /* Saturation occurred, decrease AGAIN if we can */ - if (sat_p->again > TCS_MIN_AGAIN) - sat_p->again--; - else if (sat_p->atime < TCS_MAX_ATIME) - /* reduce accumulation time by incrementing ATIME reg */ - increment_atime(sat_p); - } else if (max_val < TSC_SATURATION_LOW_BAND_LEVEL) { - /* value < 90% saturation, try to increase sensitivity */ - if (max_val <= TCS_GAIN_SAT_LEVEL) { - if (sat_p->again < TCS_MAX_AGAIN) { - sat_p->again++; - } else if (sat_p->atime > TCS_MIN_ATIME) { - /* - * increase accumulation time by decrementing - * ATIME register - */ - percent_left = TSC_SATURATION_LOW_BAND_PERCENT - - (max_val * 100 / TCS_SATURATION_LEVEL); - decrement_atime(sat_p, cur_lux, percent_left); - } - } else if (sat_p->atime > TCS_MIN_ATIME) { - /* calculate percentage between current and desired */ - percent_left = TSC_SATURATION_LOW_BAND_PERCENT - - (max_val * 100 / TCS_SATURATION_LEVEL); - - /* increase accumulation time by decrementing ATIME */ - decrement_atime(sat_p, cur_lux, percent_left); - } else if (sat_p->again < TCS_MAX_AGAIN) { - /* - * Although we're not at maximum gain yet, we - * can't just increase gain because a 4x change - * in gain under these light conditions would - * saturate on the next sample. What we can do - * is to adjust atime to reduce sensitivity so - * that we may increase gain without saturation. - * This combination effectively acts as a half - * gain increase (2.5x estimate) instead of a full - * gain increase of > 4x that would result in - * saturation. - */ - if (max_val < TCS_GAIN_UPSHIFT_LEVEL) { - sat_p->atime = TCS_GAIN_UPSHIFT_ATIME; - sat_p->again++; - } - } - } - - /* If atime or gain setting changed, update atime and gain registers */ - if (save_again != sat_p->again) { - ret = tcs3400_i2c_write8(s, TCS_I2C_CONTROL, - (sat_p->again & TCS_I2C_CONTROL_MASK)); - if (ret) - return ret; - } - - if (save_atime != sat_p->atime) { - ret = tcs3400_i2c_write8(s, TCS_I2C_ATIME, sat_p->atime); - if (ret) - return ret; - } - - return ret; -} - -/** - * normalize_channel_data - normalize the light data to remove effect of - * different atime and again settings from the sample. - */ -static uint32_t normalize_channel_data(struct motion_sensor_t *s, - uint32_t sample) -{ - struct tcs_saturation_t *sat_p = - &(TCS3400_RGB_DRV_DATA(s+1)->saturation); - const uint16_t cur_gain = (1 << (2 * sat_p->again)); - const uint16_t cal_again = (1 << (2 * TCS_CALIBRATION_AGAIN)); - - return DIV_ROUND_NEAREST(sample * (TCS_ATIME_GRANULARITY - - TCS_CALIBRATION_ATIME) * cal_again, - (TCS_ATIME_GRANULARITY - sat_p->atime) * - cur_gain); -} - - -static void tcs3400_translate_to_xyz(struct motion_sensor_t *s, - int32_t *crgb_data, int32_t *xyz_data) -{ - struct tcs3400_rgb_drv_data_t *rgb_drv_data = TCS3400_RGB_DRV_DATA(s+1); - int32_t crgb_prime[CRGB_COUNT]; - int32_t ir; - int i; - - /* IR removal */ - ir = (crgb_data[1] + crgb_data[2] + crgb_data[3] - crgb_data[0]) / 2; - for (i = 0; i < ARRAY_SIZE(crgb_prime); i++) { - if (crgb_data[i] < ir) - crgb_prime[i] = 0; - else - crgb_prime[i] = crgb_data[i] - ir; - } - - /* if CC == 0, set BC = 0 */ - if (crgb_prime[CLEAR_CRGB_IDX] == 0) - crgb_prime[BLUE_CRGB_IDX] = 0; - - /* regression fit to XYZ space */ - for (i = 0; i < 3; i++) { - const struct rgb_calibration_t *p = &rgb_drv_data->rgb_cal[i]; - - xyz_data[i] = p->offset + FP_TO_INT( - (fp_inter_t)p->coeff[RED_CRGB_IDX] * - crgb_prime[RED_CRGB_IDX] + - (fp_inter_t)p->coeff[GREEN_CRGB_IDX] * - crgb_prime[GREEN_CRGB_IDX] + - (fp_inter_t)p->coeff[BLUE_CRGB_IDX] * - crgb_prime[BLUE_CRGB_IDX] + - (fp_inter_t)p->coeff[CLEAR_CRGB_IDX] * - crgb_prime[CLEAR_CRGB_IDX]); - - if (xyz_data[i] < 0) - xyz_data[i] = 0; - } -} - -static void tcs3400_process_raw_data(struct motion_sensor_t *s, - uint8_t *raw_data_buf, - uint16_t *raw_light_data, int32_t *xyz_data) -{ - struct als_drv_data_t *als_drv_data = TCS3400_DRV_DATA(s); - struct tcs3400_rgb_drv_data_t *rgb_drv_data = TCS3400_RGB_DRV_DATA(s+1); - const uint8_t calibration_mode = rgb_drv_data->calibration_mode; - uint16_t k_channel_scale = - als_drv_data->als_cal.channel_scale.k_channel_scale; - uint16_t cover_scale = als_drv_data->als_cal.channel_scale.cover_scale; - int32_t crgb_data[CRGB_COUNT]; - int i; - - /* adjust for calibration and scale data */ - for (i = 0; i < CRGB_COUNT; i++) { - int index = i * 2; - - /* assemble the light value for this channel */ - crgb_data[i] = raw_light_data[i] = - ((raw_data_buf[index+1] << 8) | raw_data_buf[index]); - - /* in calibration mode, we only assemble the raw data */ - if (calibration_mode) - continue; - - /* rgb data at index 1, 2, and 3 owned by rgb driver, not ALS */ - if (i > 0) { - struct als_channel_scale_t *csp = - &rgb_drv_data->rgb_cal[i-1].scale; - k_channel_scale = csp->k_channel_scale; - cover_scale = csp->cover_scale; - } - - /* Step 1: divide by individual channel scale value */ - crgb_data[i] = SENSOR_APPLY_DIV_SCALE(crgb_data[i], - k_channel_scale); - - /* compensate for the light cover */ - crgb_data[i] = SENSOR_APPLY_SCALE(crgb_data[i], cover_scale); - - /* normalize the data for atime and again changes */ - crgb_data[i] = normalize_channel_data(s, crgb_data[i]); - } - - if (!calibration_mode) { - /* we're not in calibration mode & we want xyz translation */ - tcs3400_translate_to_xyz(s, crgb_data, xyz_data); - } else { - /* calibration mode returns raw data */ - for (i = 0; i < 3; i++) - xyz_data[i] = crgb_data[i+1]; - } -} - -static int tcs3400_post_events(struct motion_sensor_t *s, uint32_t last_ts) -{ - /* - * Rule says RGB sensor is right after ALS sensor. - * This routine will only get called from ALS sensor driver. - */ - struct motion_sensor_t *rgb_s = s + 1; - const uint8_t calibration_mode = - TCS3400_RGB_DRV_DATA(rgb_s)->calibration_mode; - struct ec_response_motion_sensor_data vector; - uint8_t buf[TCS_RGBC_DATA_SIZE]; /* holds raw data read from chip */ - int32_t xyz_data[3] = { 0, 0, 0 }; - uint16_t raw_data[CRGB_COUNT]; /* holds raw CRGB assembled from buf[] */ - int retries = 20; /* 400 ms max */ - int *last_v = s->raw_xyz; - int32_t data = 0; - int i, ret = EC_SUCCESS; - - /* Make sure data is valid */ - do { - ret = tcs3400_i2c_read8(s, TCS_I2C_STATUS, &data); - if (ret) - return ret; - if (!(data & TCS_I2C_STATUS_RGBC_VALID)) { - retries--; - if (retries == 0) { - CPRINTS("RGBC not valid (0x%x)", data); - return EC_ERROR_UNCHANGED; - } - msleep(20); - } - } while (!(data & TCS_I2C_STATUS_RGBC_VALID)); - - /* Read the light registers */ - ret = i2c_read_block(s->port, s->i2c_spi_addr_flags, - TCS_DATA_START_LOCATION, - buf, sizeof(buf)); - if (ret) - return ret; - - /* Process the raw light data, adjusting for scale and calibration */ - tcs3400_process_raw_data(s, buf, raw_data, xyz_data); - - /* if clear channel data changed, send illuminance upstream */ - if ((raw_data[CLEAR_CRGB_IDX] != TCS_SATURATION_LEVEL) && - (last_v[X] != xyz_data[Y])) { - if (calibration_mode) - last_v[X] = raw_data[CLEAR_CRGB_IDX]; - else - last_v[X] = xyz_data[Y]; - vector.flags = 0; - vector.data[X] = last_v[X]; - vector.data[Y] = 0; - vector.data[Z] = 0; - -#ifdef CONFIG_ACCEL_SPOOF_MODE - /* If in spoof mode, replace actual data with our fake data */ - if (s->flags & MOTIONSENSE_FLAG_IN_SPOOF_MODE) { - for (i = 0; i < 3; i++) - vector.data[i] = last_v[i] = s->spoof_xyz[i]; - } -#endif /* CONFIG_ACCEL_SPOOF_MODE */ - - if (IS_ENABLED(CONFIG_ACCEL_FIFO)) { - vector.sensor_num = s - motion_sensors; - motion_sense_fifo_stage_data(&vector, s, 3, last_ts); - } - } - - /* - * If rgb channel data changed since last sample and didn't saturate, - * send it upstream - */ - last_v = rgb_s->raw_xyz; - if (((last_v[X] != xyz_data[X]) || (last_v[Y] != xyz_data[Y]) || - (last_v[Z] != xyz_data[Z])) && - ((raw_data[RED_CRGB_IDX] != TCS_SATURATION_LEVEL) && - (raw_data[BLUE_CRGB_IDX] != TCS_SATURATION_LEVEL) && - (raw_data[GREEN_CRGB_IDX] != TCS_SATURATION_LEVEL))) { - vector.flags = 0; - if (calibration_mode) { - memcpy(vector.data, &raw_data[RED_CRGB_IDX], - sizeof(vector.data)); - memcpy(rgb_s->raw_xyz, &raw_data[RED_CRGB_IDX], - sizeof(vector.data)); - } else { - for (i = 0; i < 3; i++) - vector.data[i] = last_v[i] = xyz_data[i]; - } -#ifdef CONFIG_ACCEL_SPOOF_MODE - if (rgb_s->flags & MOTIONSENSE_FLAG_IN_SPOOF_MODE) { - for (i = 0; i < 3; i++) { - vector.data[i] = last_v[i] = - rgb_s->spoof_xyz[i]; - } - } -#endif /* CONFIG_ACCEL_SPOOF_MODE */ - -#ifdef CONFIG_ACCEL_FIFO - vector.sensor_num = rgb_s - motion_sensors; - motion_sense_fifo_stage_data(&vector, rgb_s, 3, last_ts); -#endif - } -#ifdef CONFIG_ACCEL_FIFO - motion_sense_fifo_commit_data(); -#endif - - if (!calibration_mode) - ret = tcs3400_adjust_sensor_for_saturation(s, xyz_data[Y], - raw_data); - - return ret; -} - -void tcs3400_interrupt(enum gpio_signal signal) -{ - if (IS_ENABLED(CONFIG_ACCEL_FIFO)) - last_interrupt_timestamp = __hw_clock_source_read(); - - task_set_event(TASK_ID_MOTIONSENSE, - CONFIG_ALS_TCS3400_INT_EVENT, 0); -} - -/* - * tcs3400_irq_handler - bottom half of the interrupt stack. - * Ran from the motion_sense task, finds the events that raised the interrupt, - * and posts those events via motion_sense_fifo_stage_data().. - * - * This routine will get called for the TCS3400 ALS driver, but NOT for the - * RGB driver. We harvest data for both drivers in this routine. The RGB - * driver is guaranteed to directly follow the ALS driver in the sensor list - * (i.e rgb's motion_sensor_t structure can be found at (s+1) ). - */ -static int tcs3400_irq_handler(struct motion_sensor_t *s, uint32_t *event) -{ - int status = 0; - int ret = EC_SUCCESS; - - if (!(*event & CONFIG_ALS_TCS3400_INT_EVENT)) - return EC_ERROR_NOT_HANDLED; - - ret = tcs3400_i2c_read8(s, TCS_I2C_STATUS, &status); - if (ret) - return ret; - - /* Disable future interrupts */ - ret = tcs3400_i2c_write8(s, TCS_I2C_ENABLE, TCS3400_MODE_IDLE); - if (ret) - return ret; - - if ((status & TCS_I2C_STATUS_RGBC_VALID) || - ((status & TCS_I2C_STATUS_ALS_IRQ) && - (status & TCS_I2C_STATUS_ALS_SATURATED)) || - IS_ENABLED(CONFIG_ALS_TCS3400_EMULATED_IRQ_EVENT)) { - ret = tcs3400_post_events(s, last_interrupt_timestamp); - if (ret) - return ret; - } - - tcs3400_i2c_write8(s, TCS_I2C_AICLEAR, 0); - - /* Disable ADC and turn off internal oscillator */ - ret = tcs3400_i2c_write8(s, TCS_I2C_ENABLE, TCS3400_MODE_SUSPEND); - if (ret) - return ret; - - return ret; -} - -static int tcs3400_rgb_get_scale(const struct motion_sensor_t *s, - uint16_t *scale, - int16_t *temp) -{ - struct rgb_calibration_t *rgb_cal = TCS3400_RGB_DRV_DATA(s)->rgb_cal; - - scale[X] = rgb_cal[RED_RGB_IDX].scale.k_channel_scale; - scale[Y] = rgb_cal[GREEN_RGB_IDX].scale.k_channel_scale; - scale[Z] = rgb_cal[BLUE_RGB_IDX].scale.k_channel_scale; - *temp = EC_MOTION_SENSE_INVALID_CALIB_TEMP; - return EC_SUCCESS; -} - -static int tcs3400_rgb_set_scale(const struct motion_sensor_t *s, - const uint16_t *scale, - int16_t temp) -{ - struct rgb_calibration_t *rgb_cal = TCS3400_RGB_DRV_DATA(s)->rgb_cal; - - rgb_cal[RED_RGB_IDX].scale.k_channel_scale = scale[X]; - rgb_cal[GREEN_RGB_IDX].scale.k_channel_scale = scale[Y]; - rgb_cal[BLUE_RGB_IDX].scale.k_channel_scale = scale[Z]; - return EC_SUCCESS; -} - -static int tcs3400_rgb_get_offset(const struct motion_sensor_t *s, - int16_t *offset, - int16_t *temp) -{ - offset[X] = TCS3400_RGB_DRV_DATA(s)->rgb_cal[X].offset; - offset[Y] = TCS3400_RGB_DRV_DATA(s)->rgb_cal[Y].offset; - offset[Z] = TCS3400_RGB_DRV_DATA(s)->rgb_cal[Z].offset; - *temp = EC_MOTION_SENSE_INVALID_CALIB_TEMP; - return EC_SUCCESS; -} - -static int tcs3400_rgb_set_offset(const struct motion_sensor_t *s, - const int16_t *offset, - int16_t temp) -{ - /* do not allow offset to be changed, it's predetermined */ - return EC_SUCCESS; -} - -static int tcs3400_rgb_get_data_rate(const struct motion_sensor_t *s) -{ - return 0; -} - -static int tcs3400_rgb_set_data_rate(const struct motion_sensor_t *s, - int rate, - int rnd) -{ - return EC_SUCCESS; -} - -/* Enable/disable special factory calibration mode */ -static int tcs3400_perform_calib(const struct motion_sensor_t *s, - int enable) -{ - TCS3400_RGB_DRV_DATA(s+1)->calibration_mode = enable; - return EC_SUCCESS; -} - -static int tcs3400_get_range(const struct motion_sensor_t *s) -{ - return (TCS3400_DRV_DATA(s)->als_cal.scale << 16) | - (TCS3400_DRV_DATA(s)->als_cal.uscale); -} - -static int tcs3400_set_range(const struct motion_sensor_t *s, - int range, - int rnd) -{ - TCS3400_DRV_DATA(s)->als_cal.scale = range >> 16; - TCS3400_DRV_DATA(s)->als_cal.uscale = range & 0xffff; - return EC_SUCCESS; -} - -static int tcs3400_get_scale(const struct motion_sensor_t *s, - uint16_t *scale, - int16_t *temp) -{ - scale[X] = TCS3400_DRV_DATA(s)->als_cal.channel_scale.k_channel_scale; - scale[Y] = 0; - scale[Z] = 0; - *temp = EC_MOTION_SENSE_INVALID_CALIB_TEMP; - return EC_SUCCESS; -} - -static int tcs3400_set_scale(const struct motion_sensor_t *s, - const uint16_t *scale, - int16_t temp) -{ - TCS3400_DRV_DATA(s)->als_cal.channel_scale.k_channel_scale = scale[X]; - return EC_SUCCESS; -} - -static int tcs3400_get_offset(const struct motion_sensor_t *s, - int16_t *offset, - int16_t *temp) -{ - offset[X] = TCS3400_DRV_DATA(s)->als_cal.offset; - offset[Y] = 0; - offset[Z] = 0; - *temp = EC_MOTION_SENSE_INVALID_CALIB_TEMP; - return EC_SUCCESS; -} - -static int tcs3400_set_offset(const struct motion_sensor_t *s, - const int16_t *offset, - int16_t temp) -{ - /* do not allow offset to be changed, it's predetermined */ - return EC_SUCCESS; -} - -static int tcs3400_get_data_rate(const struct motion_sensor_t *s) -{ - return TCS3400_DRV_DATA(s)->rate; -} - -static int tcs3400_set_data_rate(const struct motion_sensor_t *s, - int rate, - int rnd) -{ - enum tcs3400_mode mode; - int data; - int ret; - - if (rate == 0) { - /* Suspend driver */ - mode = TCS3400_MODE_SUSPEND; - } else { - /* - * We set the sensor for continuous mode, - * integrating over 800ms. - * Do not allow range higher than 1Hz. - */ - if (rate > TCS3400_LIGHT_MAX_FREQ) - rate = TCS3400_LIGHT_MAX_FREQ; - mode = TCS3400_MODE_COLLECTING; - } - TCS3400_DRV_DATA(s)->rate = rate; - - ret = tcs3400_i2c_read8(s, TCS_I2C_ENABLE, &data); - if (ret) - return ret; - - data = (data & TCS_I2C_ENABLE_MASK) | mode; - ret = tcs3400_i2c_write8(s, TCS_I2C_ENABLE, data); - - return ret; -} - -/** - * Initialise TCS3400 light sensor. - */ -static int tcs3400_rgb_init(const struct motion_sensor_t *s) -{ - return EC_SUCCESS; -} - -static int tcs3400_init(const struct motion_sensor_t *s) -{ - /* - * These are default power-on register values with two exceptions: - * Set ATIME = 0 (712 ms) - * Set AGAIN = 16 (0x10) (AGAIN is in CONTROL register) - */ - const struct reg_data { - uint8_t reg; - uint8_t data; - } defaults[] = { - { TCS_I2C_ENABLE, 0 }, - { TCS_I2C_ATIME, TCS_DEFAULT_ATIME }, - { TCS_I2C_WTIME, 0xFF }, - { TCS_I2C_AILTL, 0 }, - { TCS_I2C_AILTH, 0 }, - { TCS_I2C_AIHTL, 0 }, - { TCS_I2C_AIHTH, 0 }, - { TCS_I2C_PERS, 0 }, - { TCS_I2C_CONFIG, 0x40 }, - { TCS_I2C_CONTROL, (TCS_DEFAULT_AGAIN & TCS_I2C_CONTROL_MASK) }, - { TCS_I2C_AUX, 0 }, - { TCS_I2C_IR, 0 }, - { TCS_I2C_CICLEAR, 0 }, - { TCS_I2C_AICLEAR, 0 } - }; - int data = 0; - int ret; - - ret = tcs3400_i2c_read8(s, TCS_I2C_ID, &data); - if (ret) { - CPRINTS("failed reading ID reg 0x%x, ret=%d", TCS_I2C_ID, ret); - return ret; - } - if ((data != TCS340015_DEVICE_ID) && (data != TCS340037_DEVICE_ID)) { - CPRINTS("no ID match, data = 0x%x", data); - return EC_ERROR_ACCESS_DENIED; - } - - /* reset chip to default power-on settings, changes ATIME and CONTROL */ - for (int x = 0; x < ARRAY_SIZE(defaults); x++) { - ret = tcs3400_i2c_write8(s, defaults[x].reg, defaults[x].data); - if (ret) - return ret; - } - - return sensor_init_done(s); -} - -const struct accelgyro_drv tcs3400_drv = { - .init = tcs3400_init, - .read = tcs3400_read, - .set_range = tcs3400_set_range, - .get_range = tcs3400_get_range, - .set_offset = tcs3400_set_offset, - .get_offset = tcs3400_get_offset, - .set_scale = tcs3400_set_scale, - .get_scale = tcs3400_get_scale, - .set_data_rate = tcs3400_set_data_rate, - .get_data_rate = tcs3400_get_data_rate, - .perform_calib = tcs3400_perform_calib, -#ifdef CONFIG_ACCEL_INTERRUPTS - .irq_handler = tcs3400_irq_handler, -#endif -}; - -const struct accelgyro_drv tcs3400_rgb_drv = { - .init = tcs3400_rgb_init, - .read = tcs3400_rgb_read, - .set_offset = tcs3400_rgb_set_offset, - .get_offset = tcs3400_rgb_get_offset, - .set_scale = tcs3400_rgb_set_scale, - .get_scale = tcs3400_rgb_get_scale, - .set_data_rate = tcs3400_rgb_set_data_rate, - .get_data_rate = tcs3400_rgb_get_data_rate, -}; diff --git a/driver/als_tcs3400.h b/driver/als_tcs3400.h deleted file mode 100644 index 08467028b0..0000000000 --- a/driver/als_tcs3400.h +++ /dev/null @@ -1,179 +0,0 @@ -/* Copyright 2019 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. - * - * AMS TCS3400 light sensor driver - */ - -#ifndef __CROS_EC_ALS_TCS3400_H -#define __CROS_EC_ALS_TCS3400_H - -/* I2C Interface */ -#define TCS3400_I2C_ADDR_FLAGS 0x39 - -/* ID for TCS34001 and TCS34005 */ -#define TCS340015_DEVICE_ID 0x90 - -/* ID for TCS34003 and TCS34007 */ -#define TCS340037_DEVICE_ID 0x93 - -/* Register Map */ -#define TCS_I2C_ENABLE 0x80 /* R/W Enables states and interrupts */ -#define TCS_I2C_ATIME 0x81 /* R/W RGBC integration time */ -#define TCS_I2C_WTIME 0x83 /* R/W Wait time */ -#define TCS_I2C_AILTL 0x84 /* R/W Clear irq low threshold low byte */ -#define TCS_I2C_AILTH 0x85 /* R/W Clear irq low threshold high byte */ -#define TCS_I2C_AIHTL 0x86 /* R/W Clear irq high threshold low byte */ -#define TCS_I2C_AIHTH 0x87 /* R/W Clear irq high threshold high byte */ -#define TCS_I2C_PERS 0x8C /* R/W Interrupt persistence filter */ -#define TCS_I2C_CONFIG 0x8D /* R/W Configuration */ -#define TCS_I2C_CONTROL 0x8F /* R/W Gain control register */ -#define TCS_I2C_AUX 0x90 /* R/W Auxiliary control register */ -#define TCS_I2C_REVID 0x91 /* R Revision ID */ -#define TCS_I2C_ID 0x92 /* R Device ID */ -#define TCS_I2C_STATUS 0x93 /* R Device status */ -#define TCS_I2C_CDATAL 0x94 /* R Clear / IR channel low data register */ -#define TCS_I2C_CDATAH 0x95 /* R Clear / IR channel high data register */ -#define TCS_I2C_RDATAL 0x96 /* R Red ADC low data register */ -#define TCS_I2C_RDATAH 0x97 /* R Red ADC high data register */ -#define TCS_I2C_GDATAL 0x98 /* R Green ADC low data register */ -#define TCS_I2C_GDATAH 0x99 /* R Green ADC high data register */ -#define TCS_I2C_BDATAL 0x9A /* R Blue ADC low data register */ -#define TCS_I2C_BDATAH 0x9B /* R Blue ADC high data register */ -#define TCS_I2C_IR 0xC0 /* R/W Access IR Channel */ -#define TCS_I2C_IFORCE 0xE4 /* W Force Interrupt */ -#define TCS_I2C_CICLEAR 0xE6 /* W Clear channel interrupt clear */ -#define TCS_I2C_AICLEAR 0xE7 /* W Clear all interrupts */ - -#define TCS_I2C_ENABLE_POWER_ON BIT(0) -#define TCS_I2C_ENABLE_ADC_ENABLE BIT(1) -#define TCS_I2C_ENABLE_WAIT_ENABLE BIT(3) -#define TCS_I2C_ENABLE_INT_ENABLE BIT(4) -#define TCS_I2C_ENABLE_SLEEP_AFTER_INT BIT(6) -#define TCS_I2C_ENABLE_MASK (TCS_I2C_ENABLE_POWER_ON | \ - TCS_I2C_ENABLE_ADC_ENABLE | \ - TCS_I2C_ENABLE_WAIT_ENABLE | \ - TCS_I2C_ENABLE_INT_ENABLE | \ - TCS_I2C_ENABLE_SLEEP_AFTER_INT) - -enum tcs3400_mode { - TCS3400_MODE_SUSPEND = 0, - TCS3400_MODE_IDLE = (TCS_I2C_ENABLE_POWER_ON | - TCS_I2C_ENABLE_ADC_ENABLE), - TCS3400_MODE_COLLECTING = (TCS_I2C_ENABLE_POWER_ON | - TCS_I2C_ENABLE_ADC_ENABLE | - TCS_I2C_ENABLE_INT_ENABLE), -}; - -#define TCS_I2C_CONTROL_MASK 0x03 -#define TCS_I2C_STATUS_RGBC_VALID BIT(0) -#define TCS_I2C_STATUS_ALS_IRQ BIT(4) -#define TCS_I2C_STATUS_ALS_SATURATED BIT(7) - -#define TCS_I2C_AUX_ASL_INT_ENABLE BIT(5) - -/* Light data resides at 0x94 thru 0x98 */ -#define TCS_DATA_START_LOCATION TCS_I2C_CDATAL -#define TCS_CLEAR_DATA_SIZE 2 -#define TCS_RGBC_DATA_SIZE 8 - -/* Min and Max sampling frequency in mHz */ -#define TCS3400_LIGHT_MIN_FREQ 149 -#define TCS3400_LIGHT_MAX_FREQ 1000 -#if (CONFIG_EC_MAX_SENSOR_FREQ_MILLIHZ <= TCS3400_LIGHT_MAX_FREQ) -#error "EC too slow for light sensor" -#endif - -#define TCS3400_DRV_DATA(_s) ((struct als_drv_data_t *)(_s)->drv_data) -#define TCS3400_RGB_DRV_DATA(_s) \ - ((struct tcs3400_rgb_drv_data_t *)(_s)->drv_data) - -/* NOTE: The higher the ATIME value in reg, the shorter the accumulation time */ -#define TCS_MIN_ATIME 0x00 /* 712 ms */ -#define TCS_MAX_ATIME 0x70 /* 400 ms */ -#define TCS_ATIME_GRANULARITY 256 /* 256 atime settings */ -#define TCS_SATURATION_LEVEL 0xffff /* for 0 < atime < 0x70 */ -#define TCS_DEFAULT_ATIME TCS_MIN_ATIME /* 712 ms */ -#define TCS_CALIBRATION_ATIME TCS_MIN_ATIME -#define TCS_GAIN_UPSHIFT_ATIME TCS_MAX_ATIME - -/* Number of different ranges supported for atime adjustment support */ -#define TCS_MAX_ATIME_RANGES 13 -#define TCS_GAIN_TABLE_MAX_LUX 12999 -#define TCS_ATIME_GAIN_FACTOR 100 /* table values are 100x actual value */ - -#define TCS_MIN_AGAIN 0x00 /* 1x gain */ -#define TCS_MAX_AGAIN 0x03 /* 64x gain */ -#define TCS_CALIBRATION_AGAIN 0x02 /* 16x gain */ -#define TCS_DEFAULT_AGAIN TCS_CALIBRATION_AGAIN - -#define TCS_ATIME_DEC_STEP 5 -#define TCS_ATIME_INC_STEP TCS_GAIN_UPSHIFT_ATIME - -/* - * Factor to multiply light value by to determine if an increase in gain - * would cause the next value to saturate. - * - * On the TCS3400, gain increases 4x each time again register setting is - * incremented. However, I see cases where values that are 24% of saturation - * go into saturation after increasing gain, causing a back-and-forth cycle to - * occur : - * - * [134.654994 tcs3400_adjust_sensor_for_saturation value=65535 100% Gain=2 ] - * [135.655064 tcs3400_adjust_sensor_for_saturation value=15750 24% Gain=1 ] - * [136.655107 tcs3400_adjust_sensor_for_saturation value=65535 100% Gain=2 ] - * - * To avoid this, we require value to be <= 20% of saturation level - * (TCS_GAIN_SAT_LEVEL) before allowing gain to be increased. - */ -#define TCS_GAIN_ADJUST_FACTOR 5 -#define TCS_GAIN_SAT_LEVEL (TCS_SATURATION_LEVEL / TCS_GAIN_ADJUST_FACTOR) -#define TCS_UPSHIFT_FACTOR_N 25 /* upshift factor = 2.5 */ -#define TCS_UPSHIFT_FACTOR_D 10 -#define TCS_GAIN_UPSHIFT_LEVEL (TCS_SATURATION_LEVEL * TCS_UPSHIFT_FACTOR_D \ - / TCS_UPSHIFT_FACTOR_N) - -/* - * Percentage of saturation level that the auto-adjusting anti-saturation - * method will drive towards. - */ -#define TSC_SATURATION_LOW_BAND_PERCENT 90 -#define TSC_SATURATION_LOW_BAND_LEVEL (TCS_SATURATION_LEVEL * \ - TSC_SATURATION_LOW_BAND_PERCENT / 100) - -enum crbg_index { - CLEAR_CRGB_IDX = 0, - RED_CRGB_IDX, - GREEN_CRGB_IDX, - BLUE_CRGB_IDX, - CRGB_COUNT, -}; - -/* saturation auto-adjustment */ -struct tcs_saturation_t { - /* - * Gain Scaling; must be value between 0 and 3 - * 0 - 1x scaling - * 1 - 4x scaling - * 2 - 16x scaling - * 3 - 64x scaling - */ - uint8_t again; - - /* Acquisition Time, controlled by the ATIME register */ - uint8_t atime; /* ATIME register setting */ -}; - -/* tcs3400 rgb als driver data */ -struct tcs3400_rgb_drv_data_t { - uint8_t calibration_mode;/* 0 = normal run mode, 1 = calibration mode */ - - struct rgb_calibration_t rgb_cal[RGB_CHANNEL_COUNT]; - struct tcs_saturation_t saturation; /* saturation adjustment */ -}; - -extern const struct accelgyro_drv tcs3400_drv; -extern const struct accelgyro_drv tcs3400_rgb_drv; - -void tcs3400_interrupt(enum gpio_signal signal); -#endif /* __CROS_EC_ALS_TCS3400_H */ diff --git a/driver/baro_bmp280.c b/driver/baro_bmp280.c deleted file mode 100644 index 56376c8aa1..0000000000 --- a/driver/baro_bmp280.c +++ /dev/null @@ -1,390 +0,0 @@ -/* 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. - */ -/* -**************************************************************************** -* Copyright (C) 2012 - 2015 Bosch Sensortec GmbH -* -* File : bmp280.h -* -* Date : 2015/03/27 -* -* Revision : 2.0.4(Pressure and Temperature compensation code revision is 1.1) -* -* Usage: Sensor Driver for BMP280 sensor -* -**************************************************************************** -* -* \section License -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* -* Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* -* Neither the name of the copyright holder nor the names of the -* contributors may be used to endorse or promote products derived from -* this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND -* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR -* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER -* OR CONTRIBUTORS BE LIABLE FOR ANY -* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, -* OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO, -* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -* ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE -* -* The information provided is believed to be accurate and reliable. -* The copyright holder assumes no responsibility -* for the consequences of use -* of such information nor for any infringement of patents or -* other rights of third parties which may result from its use. -* No license is granted by implication or otherwise under any patent or -* patent rights of the copyright holder. -**************************************************************************/ -#include "accelgyro.h" -#include "common.h" -#include "console.h" -#include "driver/baro_bmp280.h" -#include "i2c.h" -#include "timer.h" - -#define CPRINTF(format, args...) cprintf(CC_ACCEL, format, ## args) -#define CPRINTS(format, args...) cprints(CC_ACCEL, format, ## args) - -static const uint16_t standby_durn[] = {1, 63, 125, 250, 500, 1000, 2000, 4000}; - -/* - * This function is used to get calibration parameters used for - * calculation in the registers - * - * parameter | Register address | bit - *------------|------------------|---------------- - * dig_T1 | 0x88 and 0x89 | from 0 : 7 to 8: 15 - * dig_T2 | 0x8A and 0x8B | from 0 : 7 to 8: 15 - * dig_T3 | 0x8C and 0x8D | from 0 : 7 to 8: 15 - * dig_P1 | 0x8E and 0x8F | from 0 : 7 to 8: 15 - * dig_P2 | 0x90 and 0x91 | from 0 : 7 to 8: 15 - * dig_P3 | 0x92 and 0x93 | from 0 : 7 to 8: 15 - * dig_P4 | 0x94 and 0x95 | from 0 : 7 to 8: 15 - * dig_P5 | 0x96 and 0x97 | from 0 : 7 to 8: 15 - * dig_P6 | 0x98 and 0x99 | from 0 : 7 to 8: 15 - * dig_P7 | 0x9A and 0x9B | from 0 : 7 to 8: 15 - * dig_P8 | 0x9C and 0x9D | from 0 : 7 to 8: 15 - * dig_P9 | 0x9E and 0x9F | from 0 : 7 to 8: 15 - * - * @return results of bus communication function - * @retval 0 -> Success - * - */ -static int bmp280_get_calib_param(const struct motion_sensor_t *s) -{ - int ret; - - uint8_t a_data_u8[BMP280_CALIB_DATA_SIZE] = {0}; - struct bmp280_drv_data_t *data = BMP280_GET_DATA(s); - - ret = i2c_read_block(s->port, s->i2c_spi_addr_flags, - BMP280_TEMPERATURE_CALIB_DIG_T1_LSB_REG, - a_data_u8, BMP280_CALIB_DATA_SIZE); - - if (ret) - return ret; - - /* read calibration values*/ - data->calib_param.dig_T1 = (a_data_u8[1] << 8) | a_data_u8[0]; - data->calib_param.dig_T2 = (a_data_u8[3] << 8 | a_data_u8[2]); - data->calib_param.dig_T3 = (a_data_u8[5] << 8) | a_data_u8[4]; - - data->calib_param.dig_P1 = (a_data_u8[7] << 8) | a_data_u8[6]; - data->calib_param.dig_P2 = (a_data_u8[9] << 8) | a_data_u8[8]; - data->calib_param.dig_P3 = (a_data_u8[11] << 8) | a_data_u8[10]; - data->calib_param.dig_P4 = (a_data_u8[13] << 8) | a_data_u8[12]; - data->calib_param.dig_P5 = (a_data_u8[15] << 8) | a_data_u8[14]; - data->calib_param.dig_P6 = (a_data_u8[17] << 8) | a_data_u8[16]; - data->calib_param.dig_P7 = (a_data_u8[19] << 8) | a_data_u8[18]; - data->calib_param.dig_P8 = (a_data_u8[21] << 8) | a_data_u8[20]; - data->calib_param.dig_P9 = (a_data_u8[23] << 8) | a_data_u8[22]; - - return EC_SUCCESS; -} - -static int bmp280_read_uncomp_pressure(const struct motion_sensor_t *s, - int *uncomp_pres) -{ - int ret; - uint8_t a_data_u8[BMP280_PRESSURE_DATA_SIZE] = {0}; - - ret = i2c_read_block(s->port, s->i2c_spi_addr_flags, - BMP280_PRESSURE_MSB_REG, - a_data_u8, BMP280_PRESSURE_DATA_SIZE); - - if (ret) - return ret; - - *uncomp_pres = (int32_t)((a_data_u8[0] << 12) | - (a_data_u8[1] << 4) | - (a_data_u8[2] >> 4)); - - return EC_SUCCESS; -} - -/* - * Reads actual pressure from uncompensated pressure - * and returns the value in Pascal(Pa) - * @note Output value of "96386" equals 96386 Pa = - * 963.86 hPa = 963.86 millibar - * - * Algorithm from BMP280 Datasheet Rev 1.15 Section 8.2 - * - */ -static int bmp280_compensate_pressure(const struct motion_sensor_t *s, - int uncomp_pressure) -{ - int var1, var2; - uint32_t p; - struct bmp280_drv_data_t *data = BMP280_GET_DATA(s); - - /* calculate x1 */ - var1 = (((int32_t)data->calib_param.t_fine) - >> 1) - 64000; - /* calculate x2 */ - var2 = (((var1 >> 2) * (var1 >> 2)) >> 11) - * ((int32_t)data->calib_param.dig_P6); - var2 = var2 + ((var1 * ((int32_t)data->calib_param.dig_P5)) << 1); - var2 = (var2 >> 2) + (((int32_t)data->calib_param.dig_P4) << 16); - /* calculate x1 */ - var1 = (((data->calib_param.dig_P3 * - (((var1 >> 2) * (var1 >> 2)) >> 13)) >> 3) + - ((((int32_t)data->calib_param.dig_P2) * var1) >> 1)) >> 18; - var1 = ((((32768 + var1)) * - ((int32_t)data->calib_param.dig_P1)) >> 15); - - /* Avoid exception caused by division by zero */ - if (!var1) - return 0; - - /* calculate pressure */ - p = (((uint32_t)((1048576) - uncomp_pressure) - - (var2 >> 12))) * 3125; - - /* check overflow */ - if (p < 0x80000000) - p = (p << 1) / ((uint32_t)var1); - else - p = (p / (uint32_t)var1) << 1; - - /* calculate x1 */ - var1 = (((int32_t)data->calib_param.dig_P9) * - ((int32_t)(((p >> 3) * (p >> 3)) >> 13))) >> 12; - /* calculate x2 */ - var2 = (((int32_t)(p >> 2)) * - ((int32_t)data->calib_param.dig_P8)) >> 13; - /* calculate true pressure */ - return (uint32_t)((int32_t)p + ((var1 + var2 + - data->calib_param.dig_P7) >> 4)); -} - -/* - * Set the standby duration - * standby_durn: The standby duration time value. - * value | standby duration - * ----------|-------------------- - * 0x00 | 1_MS - * 0x01 | 63_MS - * 0x02 | 125_MS - * 0x03 | 250_MS - * 0x04 | 500_MS - * 0x05 | 1000_MS - * 0x06 | 2000_MS - * 0x07 | 4000_MS - */ -static int bmp280_set_standby_durn(const struct motion_sensor_t *s, - uint8_t durn) -{ - int ret, val; - - ret = i2c_read8(s->port, s->i2c_spi_addr_flags, - BMP280_CONFIG_REG, &val); - - if (ret == EC_SUCCESS) { - val = (val & 0xE0) | ((durn << 5) & 0xE0); - /* write the standby duration*/ - ret = i2c_write8(s->port, s->i2c_spi_addr_flags, - BMP280_CONFIG_REG, val); - } - - return ret; -} - -static int bmp280_set_power_mode(const struct motion_sensor_t *s, - uint8_t power_mode) -{ - int val; - - val = (BMP280_OVERSAMP_TEMP << 5) + - (BMP280_OVERSAMP_PRES << 2) + power_mode; - - return i2c_write8(s->port, s->i2c_spi_addr_flags, - BMP280_CTRL_MEAS_REG, val); -} - -static int bmp280_set_range(const struct motion_sensor_t *s, - int range, - int rnd) -{ - struct bmp280_drv_data_t *data = BMP280_GET_DATA(s); - /* - * ->range contains the number of bit to right shift in order for the - * measurment to fit into 16 bits (or less if the AP wants to). - */ - data->range = 15 - __builtin_clz(range); - return EC_SUCCESS; -} - -static int bmp280_get_range(const struct motion_sensor_t *s) -{ - struct bmp280_drv_data_t *data = BMP280_GET_DATA(s); - - return 1 << (16 + data->range); -} - -/* - * bmp280_init() - Used to initialize barometer with default config - * - * @return results of bus communication function - * @retval 0 -> Success - */ - -static int bmp280_init(const struct motion_sensor_t *s) -{ - int val, ret; - - if (!s) - return EC_ERROR_INVAL; - - /* Read chip id */ - ret = i2c_read8(s->port, s->i2c_spi_addr_flags, - BMP280_CHIP_ID_REG, &val); - if (ret) - return ret; - - if (val != BMP280_CHIP_ID) - return EC_ERROR_INVAL; - - /* set power mode */ - ret = bmp280_set_power_mode(s, BMP280_SLEEP_MODE); - if (ret) - return ret; - - /* Read bmp280 calibration parameter */ - ret = bmp280_get_calib_param(s); - if (ret) - return ret; - - return sensor_init_done(s); -} - -static int bmp280_read(const struct motion_sensor_t *s, intv3_t v) -{ - int ret, pres; - struct bmp280_drv_data_t *data = BMP280_GET_DATA(s); - - ret = bmp280_read_uncomp_pressure(s, &pres); - - if (ret) - return ret; - - v[0] = bmp280_compensate_pressure(s, pres) >> data->range; - v[1] = v[2] = 0; - - return EC_SUCCESS; -} - -/* - * Set data rate, rate in mHz. - * Calculate the delay (in ms) to apply. - */ -static int bmp280_set_data_rate(const struct motion_sensor_t *s, int rate, - int roundup) -{ - struct bmp280_drv_data_t *data = BMP280_GET_DATA(s); - int durn, i, ret; - int period; /* Period in ms */ - - if (rate == 0) { - /* Set to sleep mode */ - data->rate = 0; - return bmp280_set_power_mode(s, BMP280_SLEEP_MODE); - } else - period = 1000000 / rate; - - /* reset power mode, waking from sleep */ - if (!data->rate) { - ret = bmp280_set_power_mode(s, BMP280_NORMAL_MODE); - if (ret) - return ret; - } - - durn = 0; - for (i = BMP280_STANDBY_CNT-1; i > 0; i--) { - if (period >= standby_durn[i] + BMP280_COMPUTE_TIME) { - durn = i; - break; - } else if (period > standby_durn[i-1] + BMP280_COMPUTE_TIME) { - durn = roundup ? i-1 : i; - break; - } - } - ret = bmp280_set_standby_durn(s, durn); - if (ret == EC_SUCCESS) - /* - * The maximum frequency is around 76Hz. Be sure it fits in 16 - * bits by shifting by one bit. - */ - data->rate = (1000000 >> BMP280_RATE_SHIFT) / - (standby_durn[durn] + BMP280_COMPUTE_TIME); - return ret; -} - -static int bmp280_get_data_rate(const struct motion_sensor_t *s) -{ - struct bmp280_drv_data_t *data = BMP280_GET_DATA(s); - - return data->rate << BMP280_RATE_SHIFT; -} - -const struct accelgyro_drv bmp280_drv = { - .init = bmp280_init, - .read = bmp280_read, - .set_range = bmp280_set_range, - .get_range = bmp280_get_range, - .set_data_rate = bmp280_set_data_rate, - .get_data_rate = bmp280_get_data_rate, -}; - -#ifdef CONFIG_CMD_I2C_STRESS_TEST_ACCEL -struct i2c_stress_test_dev bmp280_i2c_stress_test_dev = { - .reg_info = { - .read_reg = BMP280_CHIP_ID_REG, - .read_val = BMP280_CHIP_ID, - .write_reg = BMP280_CONFIG_REG, - }, - .i2c_read = &i2c_read8, - .i2c_write = &i2c_write8, -}; -#endif /* CONFIG_CMD_I2C_STRESS_TEST_ACCEL */ diff --git a/driver/baro_bmp280.h b/driver/baro_bmp280.h deleted file mode 100644 index ee95bd886f..0000000000 --- a/driver/baro_bmp280.h +++ /dev/null @@ -1,224 +0,0 @@ -/* 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. - */ -/** \mainpage -* -**************************************************************************** -* Copyright (C) 2012 - 2015 Bosch Sensortec GmbH -* -* File : bmp280.h -* -* Date : 2015/03/27 -* -* Revision : 2.0.4(Pressure and Temperature compensation code revision is 1.1) -* -* Usage: Sensor Driver for BMP280 sensor -* -**************************************************************************** -* -* \section License -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* -* Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* -* Neither the name of the copyright holder nor the names of the -* contributors may be used to endorse or promote products derived from -* this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND -* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR -* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER -* OR CONTRIBUTORS BE LIABLE FOR ANY -* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, -* OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO, -* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -* ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE -* -* The information provided is believed to be accurate and reliable. -* The copyright holder assumes no responsibility -* for the consequences of use -* of such information nor for any infringement of patents or -* other rights of third parties which may result from its use. -* No license is granted by implication or otherwise under any patent or -* patent rights of the copyright holder. -**************************************************************************/ -/* BMP280 pressure and temperature module for Chrome EC */ - -#ifndef __CROS_EC_BARO_BMP280_H -#define __CROS_EC_BARO_BMP280_H - -/* - * The addr field of barometer_sensor for I2C: - * - * +-------------------------------+---+ - * | 7 bit i2c address | 0 | - * +-------------------------------+---+ - */ - -/* - * Bit 1 of 7-bit address: 0 - If SDO is connected to GND - * Bit 1 of 7-bit address: 1 - If SDO is connected to Vddio - */ -#define BMP280_I2C_ADDRESS1_FLAGS 0x76 -#define BMP280_I2C_ADDRESS2_FLAGS 0x77 - -/* - * CHIP ID - */ -#define BMP280_CHIP_ID 0x58 -/************************************************/ -/* CALIBRATION PARAMETERS DEFINITION */ -/************************************************/ - -#define BMP280_TEMPERATURE_CALIB_DIG_T1_LSB_REG 0x88 - -/************************************************/ -/* REGISTER ADDRESS DEFINITION */ -/************************************************/ -#define BMP280_CHIP_ID_REG 0xD0 -#define BMP280_RST_REG 0xE0 /*Softreset Register */ -#define BMP280_STAT_REG 0xF3 /*Status Register */ -#define BMP280_CTRL_MEAS_REG 0xF4 /*Ctrl Measure Register */ -#define BMP280_CONFIG_REG 0xF5 /*Configuration Register */ -#define BMP280_PRESSURE_MSB_REG 0xF7 /*Pressure MSB Register */ -#define BMP280_PRESSURE_LSB_REG 0xF8 /*Pressure LSB Register */ -#define BMP280_PRESSURE_XLSB_REG 0xF9 /*Pressure XLSB Register */ -/************************************************/ -/* POWER MODE DEFINITION */ -/************************************************/ -/* Sensor Specific constants */ -#define BMP280_SLEEP_MODE 0x00 -#define BMP280_FORCED_MODE 0x01 -#define BMP280_NORMAL_MODE 0x03 -#define BMP280_SOFT_RESET_CODE 0xB6 -/************************************************/ -/* STANDBY TIME DEFINITION */ -/************************************************/ -#define BMP280_STANDBY_TIME_1_MS 0x00 -#define BMP280_STANDBY_TIME_63_MS 0x01 -#define BMP280_STANDBY_TIME_125_MS 0x02 -#define BMP280_STANDBY_TIME_250_MS 0x03 -#define BMP280_STANDBY_TIME_500_MS 0x04 -#define BMP280_STANDBY_TIME_1000_MS 0x05 -#define BMP280_STANDBY_TIME_2000_MS 0x06 -#define BMP280_STANDBY_TIME_4000_MS 0x07 -/************************************************/ -/* OVERSAMPLING DEFINITION */ -/************************************************/ -#define BMP280_OVERSAMP_SKIPPED 0x00 -#define BMP280_OVERSAMP_1X 0x01 -#define BMP280_OVERSAMP_2X 0x02 -#define BMP280_OVERSAMP_4X 0x03 -#define BMP280_OVERSAMP_8X 0x04 -#define BMP280_OVERSAMP_16X 0x05 -/************************************************/ -/* DEFINITIONS FOR ARRAY SIZE OF DATA */ -/************************************************/ -#define BMP280_PRESSURE_DATA_SIZE 3 -#define BMP280_DATA_FRAME_SIZE 6 -#define BMP280_CALIB_DATA_SIZE 24 -/*******************************************************/ -/* SAMPLING PERIOD COMPUTATION CONSTANT */ -/*******************************************************/ -#define BMP280_STANDBY_CNT 8 -#define T_INIT_MAX (20) /* (20/16 = 1.25ms) */ -#define T_MEASURE_PER_OSRS_MAX (37) /* (37/16 = 2.31ms) */ -#define T_SETUP_PRESSURE_MAX (10) /* (10/16 = 0.62ms) */ - -/* - * This is the measurement time required for pressure and temp - */ -#define BMP280_COMPUTE_TIME \ - ((T_INIT_MAX + T_MEASURE_PER_OSRS_MAX * \ - ((BIT(BMP280_OVERSAMP_TEMP) >> 1) + \ - (BIT(BMP280_OVERSAMP_PRES) >> 1)) + \ - (BMP280_OVERSAMP_PRES ? T_SETUP_PRESSURE_MAX : 0) + 15) / 16) - -/* - * These values are selected as per Bosch recommendation for - * standard handheld devices, with temp sensor not being used - */ -#define BMP280_OVERSAMP_PRES BMP280_OVERSAMP_4X -#define BMP280_OVERSAMP_TEMP BMP280_OVERSAMP_SKIPPED -/*******************************************************/ -/* GET DRIVER DATA */ -/*******************************************************/ -#define BMP280_GET_DATA(_s) \ - ((struct bmp280_drv_data_t *)(_s)->drv_data) - -/* Min and Max sampling frequency in mHz based on x4 oversampling used */ -/* FIXME - verify how chip is setup to make sure MAX is correct, manual says - * "Typical", not Max. - */ -#define BMP280_BARO_MIN_FREQ 75000 -#define BMP280_BARO_MAX_FREQ 87000 -#if (CONFIG_EC_MAX_SENSOR_FREQ_MILLIHZ <= BMP280_BARO_MAX_FREQ) -#error "EC too slow for accelerometer" -#endif - -/**************************************************************/ -/* STRUCTURE and ENUM DEFINITIONS */ -/**************************************************************/ - -/* - * struct bmp280_calib_param_t - Holds all device specific - * calibration parameters - * - * @dig_T1 to dig_T3: calibration Temp data - * @dig_P1 to dig_P9: calibration Pressure data - * @t_fine: calibration t_fine data - * - */ -struct bmp280_calib_param_t { - uint16_t dig_T1; - int16_t dig_T2; - int16_t dig_T3; - uint16_t dig_P1; - int16_t dig_P2; - int16_t dig_P3; - int16_t dig_P4; - int16_t dig_P5; - int16_t dig_P6; - int16_t dig_P7; - int16_t dig_P8; - int16_t dig_P9; - - int32_t t_fine; -}; - -/* - * struct bmp280_t - This structure holds BMP280 initialization parameters - * @calib_param: calibration data - * @rate: frequency, in mHz. - * @range: bit offset to fit data in 16 bit or less. - */ -struct bmp280_drv_data_t { - - struct bmp280_calib_param_t calib_param; - uint16_t rate; - uint16_t range; -}; -#define BMP280_RATE_SHIFT 1 - -extern const struct accelgyro_drv bmp280_drv; - -#ifdef CONFIG_CMD_I2C_STRESS_TEST_ACCEL -extern struct i2c_stress_test_dev bmp280_i2c_stress_test_dev; -#endif - -#endif diff --git a/driver/battery/bq20z453.c b/driver/battery/bq20z453.c deleted file mode 100644 index 3cd16e8b8f..0000000000 --- a/driver/battery/bq20z453.c +++ /dev/null @@ -1,35 +0,0 @@ -/* Copyright 2012 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. - * - * Smart battery driver for BQ20Z453. - */ - -#include "battery_smart.h" -#include "hooks.h" -#include "host_command.h" - -#define PARAM_CUT_OFF 0x0010 - -static void cutoff(void) -{ - /* Claim i2c and send cutoff command to battery. */ - sb_write(SB_MANUFACTURER_ACCESS, PARAM_CUT_OFF); -} -DECLARE_DEFERRED(cutoff); - -enum ec_status battery_command_cut_off(struct host_cmd_handler_args *args) -{ - /* - * Queue battery cutoff. This must be deferred so we can send the - * response to the host first. Some platforms (snow) share an I2C bus - * between the EC, AP, and battery, so we need the host to complete the - * transaction and release the I2C bus before we'll be abl eto send the - * cutoff command. - */ - hook_call_deferred(&cutoff_data, 1000); - - return EC_RES_SUCCESS; -} -DECLARE_HOST_COMMAND(EC_CMD_BATTERY_CUT_OFF, battery_command_cut_off, - EC_VER_MASK(0)); diff --git a/driver/battery/bq27541.c b/driver/battery/bq27541.c deleted file mode 100644 index b9c80c3b24..0000000000 --- a/driver/battery/bq27541.c +++ /dev/null @@ -1,350 +0,0 @@ -/* Copyright 2013 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. - * - * Battery driver for BQ27541/BQ27741/BQ27742. - */ - -#include "battery.h" -#include "console.h" -#include "extpower.h" -#include "hooks.h" -#include "i2c.h" -#include "util.h" - -#define BQ27541_ADDR_FLAGS 0x55 -#define BQ27541_TYPE_ID 0x0541 -#define BQ27741_TYPE_ID 0x0741 -#define BQ27742_TYPE_ID 0x0742 - -#define REG_CTRL 0x00 -#define REG_AT_RATE 0x02 -#define REG_AT_RATE_TIME_TO_EMPTY 0x04 -#define REG_TEMPERATURE 0x06 -#define REG_VOLTAGE 0x08 -#define REG_FLAGS 0x0a -#define REG_NOMINAL_CAPACITY 0x0c -#define REG_FULL_AVAILABLE_CAPACITY 0x0e -#define REG_REMAINING_CAPACITY 0x10 -#define REG_FULL_CHARGE_CAPACITY 0x12 -#define REG_AVERAGE_CURRENT 0x14 -#define REG_TIME_TO_EMPTY 0x16 -#define REG_TIME_TO_FULL 0x18 -#define REG_STANDBY_CURRENT 0x1a -#define REG_STANDBY_TIME_TO_EMPTY 0x1c -#define REG_MAX_LOAD_CURRENT 0x1e -#define REG_MAX_LOAD_TIME_TO_EMPTY 0x20 -#define REG_AVAILABLE_ENERGY 0x22 -#define REG_AVERAGE_POEWR 0x24 -#define REG_TT_EAT_CONSTANT_POWER 0x26 -#define REG_CYCLE_COUNT 0x2a -#define REG_STATE_OF_CHARGE 0x2c -#define REG_DESIGN_CAPACITY 0x3c -#define REG_DEVICE_NAME_LENGTH 0x62 -#define MAX_DEVICE_NAME_LENGTH 7 -#define REG_DEVICE_NAME 0x63 -#define REG_PROTECTOR 0x6d - -static int battery_type_id; -static int fake_state_of_charge = -1; - -static int bq27541_read(int offset, int *data) -{ - return i2c_read16(I2C_PORT_BATTERY, BQ27541_ADDR, offset, data); -} - -static int bq27541_read8(int offset, int *data) -{ - return i2c_read8(I2C_PORT_BATTERY, BQ27541_ADDR, offset, data); -} - -static int bq27541_write(int offset, int data) -{ - return i2c_write16(I2C_PORT_BATTERY, BQ27541_ADDR, offset, data); -} - -int bq27541_probe(void) -{ - int rv; - - rv = bq27541_write(REG_CTRL, 0x1); - rv |= bq27541_read(REG_CTRL, &battery_type_id); - - if (rv) - return rv; - if (battery_type_id == BQ27541_TYPE_ID || - battery_type_id == BQ27741_TYPE_ID || - battery_type_id == BQ27742_TYPE_ID) - return EC_SUCCESS; - return EC_ERROR_UNKNOWN; -} - -static void probe_type_id(void) -{ - bq27541_probe(); -} -DECLARE_HOOK(HOOK_INIT, probe_type_id, HOOK_PRIO_DEFAULT); - -int battery_device_name(char *device_name, int buf_size) -{ - int rv, i, val; - int len = MIN(7, buf_size - 1); - - if (battery_type_id == BQ27742_TYPE_ID) { - /* No device name register available */ - strzcpy(device_name, "<BATT>", len); - return 0; - } - - rv = bq27541_read8(REG_DEVICE_NAME_LENGTH, &val); - if (rv) - return rv; - len = MIN(len, val); - - for (i = 0; i < len; ++i) { - rv |= bq27541_read8(REG_DEVICE_NAME + i, &val); - device_name[i] = val; - } - device_name[i] = '\0'; - - return rv; -} - -int battery_state_of_charge_abs(int *percent) -{ - return EC_ERROR_UNIMPLEMENTED; -} - -int battery_remaining_capacity(int *capacity) -{ - return bq27541_read(REG_REMAINING_CAPACITY, capacity); -} - -int battery_full_charge_capacity(int *capacity) -{ - return bq27541_read(REG_FULL_CHARGE_CAPACITY, capacity); -} - -int battery_time_to_empty(int *minutes) -{ - return bq27541_read(REG_TIME_TO_EMPTY, minutes); -} - -int battery_time_to_full(int *minutes) -{ - return bq27541_read(REG_TIME_TO_FULL, minutes); -} - -int battery_cycle_count(int *count) -{ - return bq27541_read(REG_CYCLE_COUNT, count); -} - -int battery_design_capacity(int *capacity) -{ - return bq27541_read(REG_DESIGN_CAPACITY, capacity); -} - -int battery_time_at_rate(int rate, int *minutes) -{ - int rv; - - rv = bq27541_write(REG_AT_RATE, rate); - if (rv) - return rv; - return bq27541_read(REG_AT_RATE_TIME_TO_EMPTY, minutes); -} - -int battery_device_chemistry(char *dest, int size) -{ - strzcpy(dest, "<unkn>", size); - - return EC_SUCCESS; -} - -int battery_serial_number(int *serial) -{ - *serial = 0x0BAD0BAD; - - return EC_SUCCESS; -} - -int battery_design_voltage(int *voltage) -{ - *voltage = battery_get_info()->voltage_normal; - - return EC_SUCCESS; -} - -/** - * Check if battery allows charging. - * - * @param allowed Non-zero if charging allowed; zero if not allowed. - * @return non-zero if error. - */ -static int battery_charging_allowed(int *allowed) -{ - int rv, val; - - rv = bq27541_read(REG_FLAGS, &val); - if (rv) - return rv; - if (battery_type_id == BQ27541_TYPE_ID || - battery_type_id == BQ27741_TYPE_ID) - *allowed = (val & 0x100); - else /* BQ27742_TYPE_ID */ - *allowed = (val & 0x8); - - return EC_SUCCESS; -} - -int battery_get_mode(int *mode) -{ - return EC_ERROR_UNIMPLEMENTED; -} - -int battery_status(int *status) -{ - return EC_ERROR_UNIMPLEMENTED; -} - -enum battery_present battery_is_present(void) -{ - int v; - if (bq27541_read(REG_TEMPERATURE, &v)) - return BP_NOT_SURE; - return BP_YES; -} - -void battery_get_params(struct batt_params *batt) -{ - int v; - const uint32_t flags_to_check = BATT_FLAG_BAD_TEMPERATURE | - BATT_FLAG_BAD_STATE_OF_CHARGE | - BATT_FLAG_BAD_VOLTAGE | - BATT_FLAG_BAD_CURRENT; - - /* Reset flags */ - batt->flags = 0; - - if (bq27541_read(REG_TEMPERATURE, &batt->temperature)) - batt->flags |= BATT_FLAG_BAD_TEMPERATURE; - - if (bq27541_read8(REG_STATE_OF_CHARGE, &v) && fake_state_of_charge < 0) - batt->flags |= BATT_FLAG_BAD_STATE_OF_CHARGE; - - batt->state_of_charge = fake_state_of_charge >= 0 ? - fake_state_of_charge : v; - - if (bq27541_read(REG_VOLTAGE, &batt->voltage)) - batt->flags |= BATT_FLAG_BAD_VOLTAGE; - - v = 0; - if (bq27541_read(REG_AVERAGE_CURRENT, &v)) - batt->flags |= BATT_FLAG_BAD_CURRENT; - batt->current = (int16_t)v; - - /* Default to not desiring voltage and current */ - batt->desired_voltage = batt->desired_current = 0; - - /* If any of those reads worked, the battery is responsive */ - if ((batt->flags & flags_to_check) != flags_to_check) { - batt->flags |= BATT_FLAG_RESPONSIVE; - batt->is_present = BP_YES; - } else { - batt->is_present = BP_NOT_SURE; - } - - v = 0; - if (battery_charging_allowed(&v)) { - batt->flags |= BATT_FLAG_BAD_ANY; - } else if (v) { - batt->flags |= BATT_FLAG_WANT_CHARGE; - - /* - * Desired voltage and current are not provided by the battery. - * So ask for battery's max voltage and an arbitrarily large - * current. - */ - batt->desired_voltage = battery_get_info()->voltage_max; - batt->desired_current = 4096; - } -} - -/* Wait until battery is totally stable */ -int battery_wait_for_stable(void) -{ - /* TODO(crosbug.com/p/30426): implement me */ - return EC_SUCCESS; -} - -#ifdef CONFIG_BATTERY_REVIVE_DISCONNECT -/* - * Check if battery is in disconnect state, a state entered by pulling - * BATT_DISCONN_N low, and clear that state if we have external power plugged - * and no battery faults are detected. Disconnect state resembles battery - * shutdown mode, but extra steps must be taken to get the battery out of this - * mode. - */ -enum battery_disconnect_state battery_get_disconnect_state(void) -{ - int val, rv; - /* - * Take note if we find that the battery isn't in disconnect state, - * and always return NOT_DISCONNECTED without probing the battery. - * This assumes the battery will not go to disconnect state during - * runtime. - */ - static int not_disconnected; - - if (not_disconnected) - return BATTERY_NOT_DISCONNECTED; - - if (extpower_is_present()) { - /* Check DSG_OFF bit */ - rv = bq27541_read(REG_PROTECTOR, &val); - if (rv) - return BATTERY_DISCONNECT_ERROR; - if (!(val & BIT(6))) { - not_disconnected = 1; - return BATTERY_NOT_DISCONNECTED; - } - - /* DSG_OFF is set. Verify this is not due to a safety fault */ - if (val & 0x3f) - return BATTERY_DISCONNECT_ERROR; - rv = bq27541_read(REG_FLAGS, &val); - if (rv) - return BATTERY_DISCONNECT_ERROR; - if (val & 0xfc60) - return BATTERY_DISCONNECT_ERROR; - return BATTERY_DISCONNECTED; - } - not_disconnected = 1; - return BATTERY_NOT_DISCONNECTED; -} -#endif /* CONFIG_BATTERY_REVIVE_DISCONNECT */ - -static int command_battfake(int argc, char **argv) -{ - char *e; - int v; - - if (argc == 2) { - v = strtoi(argv[1], &e, 0); - if (*e || v < -1 || v > 100) - return EC_ERROR_PARAM1; - - fake_state_of_charge = v; - } - - if (fake_state_of_charge >= 0) - ccprintf("Fake batt %d%%\n", - fake_state_of_charge); - - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(battfake, command_battfake, - "percent (-1 = use real level)", - "Set fake battery level"); - diff --git a/driver/battery/bq27621_g1.c b/driver/battery/bq27621_g1.c deleted file mode 100644 index 8445516600..0000000000 --- a/driver/battery/bq27621_g1.c +++ /dev/null @@ -1,742 +0,0 @@ -/* Copyright 2014 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. - * - * Battery driver for BQ27621-G1 - */ - -#include "battery.h" -#include "console.h" -#include "extpower.h" -#include "hooks.h" -#include "i2c.h" -#include "util.h" -#include "timer.h" - -#define BQ27621_ADDR_FLAGS 0x55 -#define BQ27621_TYPE_ID 0x0621 - -#define REG_CTRL 0x00 -#define REG_TEMPERATURE 0x02 -#define REG_VOLTAGE 0x04 -#define REG_FLAGS 0x06 -#define REG_NOMINAL_CAPACITY 0x08 -#define REG_FULL_AVAILABLE_CAPACITY 0x0a -#define REG_REMAINING_CAPACITY 0x0c -#define REG_FULL_CHARGE_CAPACITY 0x0e -#define REG_EFFECTIVE_CURRENT 0x10 -#define REG_AVERAGE_POWER 0x18 -#define REG_STATE_OF_CHARGE 0x1c -#define REG_INTERNAL_TEMPERATURE 0x1e -#define REG_REMAINING_CAPACITY_UNFILTERED 0x28 -#define REG_REMAINING_CAPACITY_FILTERED 0x2a -#define REG_FULL_CHARGE_CAPACITY_UNFILTERED 0x28 -#define REG_FULL_CHARGE_CAPACITY_FILTERED 0x2a -#define REG_STATE_OF_CHARGE_UNFILTERED 0x30 -#define REG_OP_CONFIG 0x3a -#define REG_DESIGN_CAPACITY 0x3c -#define REG_DATA_CLASS 0x3e -#define REG_DATA_BLOCK 0x3f -#define REG_BLOCK_DATA_CHECKSUM 0x60 -#define REG_BLOCK_DATA_CONTROL 0x61 - -#define REGISTERS_BLOCK_OFFSET 64 -#define REGISTERS_BLOCK_OP_CONFIG 0x40 -#define REGISTERS_BLOCK_OP_CONFIG_B 0x42 -#define REGISTERS_BLOCK_DF_VERSION 0x43 - -/* State block */ -#define STATE_BLOCK_OFFSET 82 -#define STATE_BLOCK_DESIGN_CAPACITY 0x43 -#define STATE_BLOCK_DESIGN_ENERGY 0x45 -#define STATE_BLOCK_TERMINATE_VOLTAGE 0x49 -#define STATE_BLOCK_TAPER_RATE 0x54 - -/* BQ27621 Control subcommands */ -#define CONTROL_CONTROL_STATUS 0x00 -#define CONTROL_DEVICE_TYPE 0x01 -#define CONTROL_FW_VERSION 0x02 -#define CONTROL_PREV_MACWRITE 0x07 -#define CONTROL_CHEM_ID 0x08 -#define CONTROL_BAT_INSERT 0x0C -#define CONTROL_BAT_REMOVE 0x0D -#define CONTROL_TOGGLE_POWERMIN 0x10 -#define CONTROL_SET_HIBERNATE 0x11 -#define CONTROL_CLEAR_HIBERNATE 0x12 -#define CONTROL_SET_CFGUPDATE 0x13 -#define CONTROL_SHUTDOWN_ENABLE 0x1B -#define CONTROL_SHUTDOWN 0x1C -#define CONTROL_SEALED 0x20 -#define CONTROL_TOGGLE_GPOUT 0x23 -#define CONTROL_ALT_CHEM1 0x31 -#define CONTROL_ALT_CHEM2 0x32 -#define CONTROL_RESET 0x41 -#define CONTROL_SOFT_RESET 0x42 -#define CONTROL_EXIT_CFGUPDATE 0x43 -#define CONTROL_EXIT_RESIM 0x44 -#define CONTROL_UNSEAL 0x8000 - -/* BQ27621 Status bits */ -#define STATUS_SHUTDOWNEN 0x8000 -#define STATUS_WDRESET 0x4000 -#define STATUS_SS 0x2000 -#define STATUS_CALMODE 0x1000 -#define STATUS_OCVCMDCOMP 0x0200 -#define STATUS_OCVFAIL 0x0100 -#define STATUS_INITCOMP 0x0080 -#define STATUS_HIBERNATE 0x0040 -#define STATUS_POWERMIN 0x0020 -#define STATUS_SLEEP 0x0010 -#define STATUS_LDMD 0x0008 -#define STATUS_CHEMCHNG 0x0001 - -/* BQ27621 Flags bits */ -#define FLAGS_OT 0x8000 -#define FLAGS_UT 0x4000 -#define FLAGS_FC 0x0200 -#define FLAGS_CHG 0x0100 -#define FLAGS_OCVTAKEN 0x0080 -#define FLAGS_ITPOR 0x0020 -#define FLAGS_CFGUPD 0x0010 -#define FLAGS_BAT_DET 0x0008 -#define FLAGS_SOC1 0x0004 -#define FLAGS_SOCF 0x0002 -#define FLAGS_DSG 0x0001 - -/* - * There are some parameters that need to be defined in the board file: - * BQ27621_TOGGLE_POWER_MIN - Put it in minimum power mode - * (may affect I2C timing) - * BQ27621_DESIGN_CAPACITY - mAh - * BQ27621_DESIGN_ENERGY - Design Capacity x 3.7 - * BQ27621_TERMINATE_VOLTAGE - mV - * BQ27621_TAPER_CURRENT - mA - * BQ27621_CHEM_ID - 0x1202 (DEFAULT) 0x1210 (ALT_CHEM1) - * 0x354 (ALT_CHEM2) - * - * For extra large or extra small batteries, this driver scales everything but - * voltages. The recommended range is 150mAh - 6Ah - * - */ - -#define BQ27621_SCALE_FACTOR (BQ27621_DESIGN_CAPACITY < 150 ? 10.0 : \ - (BQ27621_DESIGN_CAPACITY > 6000 ? 0.1 : 1)) - -#define BQ27621_UNSCALE(x) (BQ27621_SCALE_FACTOR == 10 ? (x) / 10 : \ - (BQ27621_SCALE_FACTOR == 0.1 ? (x) * 10 : (x))) - -#define BQ27621_TAPER_RATE ((int)(BQ27621_DESIGN_CAPACITY/ \ - (0.1 * BQ27621_TAPER_CURRENT))) - -#define BQ27621_SCALED_DESIGN_CAPACITY ((int)(BQ27621_DESIGN_CAPACITY * \ - BQ27621_SCALE_FACTOR)) -#define BQ27621_SCALED_DESIGN_ENERGY ((int)(BQ27621_DESIGN_CAPACITY * \ - BQ27621_SCALE_FACTOR)) - -/* - *Everything is LSB first. Parameters need to be converted. - * - * The values from the data sheet are already LSB-first. - */ - -#define ENDIAN_SWAP_2B(x) ((((x) & 0xff) << 8) | (((x) & 0xff00) >> 8)) -#define DESIGN_CAPACITY ENDIAN_SWAP_2B(BQ27621_SCALED_DESIGN_CAPACITY) -#define DESIGN_ENERGY ENDIAN_SWAP_2B(BQ27621_SCALED_DESIGN_ENERGY) -#define TAPER_RATE ENDIAN_SWAP_2B(BQ27621_TAPER_RATE) -#define TERMINATE_VOLTAGE ENDIAN_SWAP_2B(BQ27621_TERMINATE_VOLTAGE) - -struct battery_info battery_params; - -static int bq27621_read(int offset, int *data) -{ - return i2c_read16(I2C_PORT_BATTERY, BQ27621_ADDR, offset, data); -} - -static int bq27621_read8(int offset, int *data) -{ - return i2c_read8(I2C_PORT_BATTERY, BQ27621_ADDR, offset, data); -} - -static int bq27621_write(int offset, int data) -{ - return i2c_write16(I2C_PORT_BATTERY, BQ27621_ADDR, offset, data); -} - -static int bq27621_write8(int offset, int data) -{ - return i2c_write8(I2C_PORT_BATTERY, BQ27621_ADDR, offset, data); -} - -static int bq27621_probe(void) -{ - int rv; - int battery_type_id; - - /* Delays need to be added for correct operation at > 100Kbps */ - ASSERT(i2c_ports[I2C_PORT_BATTERY].kbps <= 100); - - rv = bq27621_write(REG_CTRL, CONTROL_DEVICE_TYPE); - rv |= bq27621_read(REG_CTRL, &battery_type_id); - - if (rv) - return rv; - if (battery_type_id == BQ27621_TYPE_ID) { - battery_params.voltage_max = BATTERY_VOLTAGE_MAX; - battery_params.voltage_normal = BATTERY_VOLTAGE_NORMAL; - battery_params.voltage_min = BATTERY_VOLTAGE_MIN; - return EC_SUCCESS; - } - return EC_ERROR_UNKNOWN; -} - -static inline int bq27621_unseal(void) -{ - return bq27621_write(REG_CTRL, CONTROL_UNSEAL) | - bq27621_write(REG_CTRL, CONTROL_UNSEAL); -} - -static int bq27621_enter_config_update(void) -{ - int tries, flags = 0, rv = EC_SUCCESS; - - /* Enter Config Update Mode (Can take up to a second) */ - for (tries = 2000; tries > 0 && !(flags & FLAGS_CFGUPD) && - (rv == EC_SUCCESS); tries--) { - rv |= bq27621_write(REG_CTRL, CONTROL_SET_CFGUPDATE); - rv |= bq27621_read(REG_FLAGS, &flags); - } - - if (tries == 0) - return EC_ERROR_TIMEOUT; - else - return EC_SUCCESS; -} - -static int bq27621_enter_block_mode(int block) -{ - int rv; - rv = bq27621_write8(REG_BLOCK_DATA_CONTROL, 0); - rv |= bq27621_write8(REG_DATA_CLASS, block); - rv |= bq27621_write8(REG_DATA_BLOCK, 0); - udelay(500); /* Shouldn't be needed, doesn't work without it. */ - return rv; -} - -static int bq27621_seal(void) -{ - int rv = 0; - int status = 0, param = 0, checksum = 0; - - rv |= bq27621_write(REG_CTRL, CONTROL_CONTROL_STATUS); - rv |= bq27621_read(REG_CTRL, &status); - - if (status & STATUS_SS) /* Already sealed */ - return EC_SUCCESS; - - /* Enter Config Update Mode */ - rv = bq27621_enter_config_update(); - - if (rv) - return rv; - - /* Set up block RAM update */ - rv = bq27621_enter_block_mode(REGISTERS_BLOCK_OFFSET); - - if (rv) - return rv; - - rv = bq27621_read8(REG_BLOCK_DATA_CHECKSUM, &checksum); - - if (rv) - return rv; - - checksum = 0xff - checksum; - - rv = bq27621_read8(REGISTERS_BLOCK_OP_CONFIG_B, ¶m); - checksum -= param; /* 1B */ - - param |= 1<<5; /* Set DEF_SEAL */ - - rv = bq27621_write8(REGISTERS_BLOCK_OP_CONFIG_B, param); - checksum += param; /* 1B */ - - checksum = 0xff - (0xff & checksum); - - rv = bq27621_write8(REG_BLOCK_DATA_CHECKSUM, checksum); - - if (rv) - return rv; - - /* Exit Update */ - rv = bq27621_write(REG_CTRL, CONTROL_SOFT_RESET); - - return rv; -} - -#define CHECKSUM_2B(x) ((x & 0xff) + ((x>>8) & 0xff)) - -static int bq27621_init(void) -{ - int rv; - int status = 0, param = 0, checksum = 0; - - rv = bq27621_probe(); - - if (rv) - return rv; - - /* Unseal the device if necessary */ - rv |= bq27621_write(REG_CTRL, CONTROL_CONTROL_STATUS); - rv |= bq27621_read(REG_CTRL, &status); - - if (status & STATUS_SS) - rv |= bq27621_unseal(); - - if (rv) - return rv; - - /* Select the alternate chemistry if needed */ - rv = bq27621_write(REG_CTRL, CONTROL_CHEM_ID); - rv |= bq27621_read(REG_CTRL, ¶m); - - if (param != BQ27621_CHEM_ID) { /* Change needed */ - - if (BQ27621_CHEM_ID == 0x1202) { /* Return to default */ - rv |= bq27621_write(REG_CTRL, CONTROL_RESET); - } else { - rv |= bq27621_enter_config_update(); - - if (BQ27621_CHEM_ID == 0x1210) - rv |= bq27621_write(REG_CTRL, - CONTROL_ALT_CHEM1); - if (BQ27621_CHEM_ID == 0x0354) - rv |= bq27621_write(REG_CTRL, - CONTROL_ALT_CHEM2); - - /* - * The datasheet recommends checking the status here. - * - * If the CHEMCHG is active, it wasn't successful. - * - * There's no recommendation for what to do if it isn't. - */ - - rv |= bq27621_write(REG_CTRL, CONTROL_EXIT_CFGUPDATE); - } - } - - if (rv) - return rv; - - rv = bq27621_enter_config_update(); - - if (rv) - return rv; - - /* Set up block RAM update */ - rv = bq27621_enter_block_mode(STATE_BLOCK_OFFSET); - - if (rv) - return rv; - - rv = bq27621_read8(REG_BLOCK_DATA_CHECKSUM, &checksum); - if (rv) - return rv; - - checksum = 0xff - checksum; - - rv = bq27621_read(STATE_BLOCK_DESIGN_CAPACITY, ¶m); - checksum -= CHECKSUM_2B(param); - - rv |= bq27621_read(STATE_BLOCK_DESIGN_ENERGY, ¶m); - checksum -= CHECKSUM_2B(param); - - rv |= bq27621_read(STATE_BLOCK_TERMINATE_VOLTAGE, ¶m); - checksum -= CHECKSUM_2B(param); - - rv |= bq27621_read(STATE_BLOCK_TAPER_RATE, ¶m); - checksum -= CHECKSUM_2B(param); - - if (rv) - return rv; - - rv = bq27621_write(STATE_BLOCK_DESIGN_CAPACITY, DESIGN_CAPACITY); - checksum += CHECKSUM_2B(DESIGN_CAPACITY); - - rv |= bq27621_write(STATE_BLOCK_DESIGN_ENERGY, DESIGN_ENERGY); - checksum += CHECKSUM_2B(DESIGN_ENERGY); - - rv |= bq27621_write(STATE_BLOCK_TERMINATE_VOLTAGE, TERMINATE_VOLTAGE); - checksum += CHECKSUM_2B(TERMINATE_VOLTAGE); - - rv |= bq27621_write(STATE_BLOCK_TAPER_RATE, TAPER_RATE); - checksum += CHECKSUM_2B(TAPER_RATE); - - checksum = 0xff - (0xff & checksum); - - - if (rv) - return rv; - - rv = bq27621_write8(REG_BLOCK_DATA_CHECKSUM, checksum); - - rv |= bq27621_write(REG_CTRL, CONTROL_SOFT_RESET); - - if (rv) - return rv; - - bq27621_seal(); - - return rv; -} - -static void probe_type_id_init(void) -{ - int rv = EC_SUCCESS; - - rv = bq27621_probe(); - - if (rv) - return; - - rv = bq27621_init(); - - if (rv) { /* Try it once more */ - rv = bq27621_write(REG_CTRL, CONTROL_RESET); - rv |= bq27621_init(); - } -} - -DECLARE_HOOK(HOOK_INIT, probe_type_id_init, HOOK_PRIO_DEFAULT); - -/* Some of the functions to make this battery "smart" */ - -int battery_device_name(char *device_name, int buf_size) -{ - return EC_ERROR_UNIMPLEMENTED; -} - -int battery_state_of_charge_abs(int *percent) -{ - return EC_ERROR_UNIMPLEMENTED; -} - -int battery_remaining_capacity(int *capacity) -{ - int scaled_value, err_code; - - err_code = bq27621_read(REG_REMAINING_CAPACITY, &scaled_value); - - *capacity = BQ27621_UNSCALE(scaled_value); - - return err_code; -} - -int battery_full_charge_capacity(int *capacity) -{ - int scaled_value, err_code; - - err_code = bq27621_read(REG_FULL_CHARGE_CAPACITY, &scaled_value); - - *capacity = BQ27621_UNSCALE(scaled_value); - - return err_code; -} - -int battery_time_to_empty(int *minutes) -{ - return EC_ERROR_UNIMPLEMENTED; -} - -int battery_time_to_full(int *minutes) -{ - return EC_ERROR_UNIMPLEMENTED; -} - -int battery_cycle_count(int *count) -{ - return EC_ERROR_UNIMPLEMENTED; -} - -int battery_design_capacity(int *capacity) -{ - int scaled_value, err_code; - - err_code = bq27621_read(REG_DESIGN_CAPACITY, &scaled_value); - - *capacity = BQ27621_UNSCALE(scaled_value); - - return err_code; -} - -int battery_time_at_rate(int rate, int *minutes) -{ - return EC_ERROR_UNIMPLEMENTED; -} - -int battery_device_chemistry(char *dest, int size) -{ - uint32_t rv; - int param; - - rv = bq27621_write(REG_CTRL, CONTROL_CHEM_ID); - rv |= bq27621_read(REG_CTRL, ¶m); - - if (param == 0x1202) - strzcpy(dest, "0x1202 (default)", size); - if (param == 0x1210) - strzcpy(dest, "0x1210 (ALT_CHEM1)", size); - if (param == 0x0354) - strzcpy(dest, "0x0354 (ALT_CHEM2)", size); - - return EC_SUCCESS; -} - -int battery_serial_number(int *serial) -{ - return EC_ERROR_UNIMPLEMENTED; -} - -int battery_design_voltage(int *voltage) -{ - *voltage = BATTERY_VOLTAGE_NORMAL; - - return EC_SUCCESS; -} - -int battery_get_mode(int *mode) -{ - return EC_ERROR_UNIMPLEMENTED; -} - -int battery_status(int *status) -{ - return EC_ERROR_UNIMPLEMENTED; -} - -enum battery_present battery_is_present(void) -{ - return EC_ERROR_UNIMPLEMENTED; -} - -void battery_get_params(struct batt_params *batt) -{ - /* Reset flags */ - batt->flags = 0; - - if (bq27621_read(REG_TEMPERATURE, &batt->temperature)) - batt->flags |= BATT_FLAG_BAD_TEMPERATURE; - else - batt->flags |= BATT_FLAG_RESPONSIVE; /* Battery is responding */ - - if (bq27621_read8(REG_STATE_OF_CHARGE, &batt->state_of_charge)) - batt->flags |= BATT_FLAG_BAD_STATE_OF_CHARGE; - - if (bq27621_read(REG_VOLTAGE, &batt->voltage)) - batt->flags |= BATT_FLAG_BAD_VOLTAGE; - - batt->flags |= BATT_FLAG_BAD_CURRENT; - batt->current = 0; - - /* Default to not desiring voltage and current */ - batt->desired_voltage = batt->desired_current = 0; -} - -/* Wait until battery is totally stable */ -int battery_wait_for_stable(void) -{ - /* TODO(crosbug.com/p/30426): implement me */ - return EC_SUCCESS; -} - -#ifdef CONFIG_CMD_BATDEBUG - #define CPRINTF(format, args...) cprintf(CC_I2C, format, ## args) -#else - #define CPRINTF(format, args...) -#endif - -#ifdef CONFIG_CMD_BATDEBUG - -static int command_fgunseal(int argc, char **argv) -{ - int rv = EC_SUCCESS; - - if (argc > 1) - return EC_ERROR_PARAM_COUNT; - - rv = bq27621_unseal(); - - return rv; -} - -DECLARE_CONSOLE_COMMAND(fgunseal, command_fgunseal, - "", - "Unseal the fg"); - -static int command_fgseal(int argc, char **argv) -{ - int rv = EC_SUCCESS; - - if (argc > 1) - return EC_ERROR_PARAM_COUNT; - - rv = bq27621_seal(); - - return rv; -} - -DECLARE_CONSOLE_COMMAND(fgseal, command_fgseal, - "", - "Seal the fg"); - -static int command_fginit(int argc, char **argv) -{ - int rv = EC_SUCCESS; - int force = 0; - int flags = 0; - int unconfigured = 0; - char *e; - - if (argc > 2) - return EC_ERROR_PARAM_COUNT; - - if (argc == 2) { - force = strtoi(argv[1], &e, 0); - if (*e) - return EC_ERROR_PARAM1; - } - - rv = bq27621_read(REG_FLAGS, &flags); - unconfigured = flags & FLAGS_ITPOR; - - if (!unconfigured && force) { - rv |= bq27621_write(REG_CTRL, CONTROL_RESET); - unconfigured = (rv == EC_SUCCESS); - } - - if (unconfigured) - rv |= bq27621_init(); - - return rv; -} - -DECLARE_CONSOLE_COMMAND(fginit, command_fginit, - "[force]", - "Initialize the fg"); - -static int command_fgprobe(int argc, char **argv) -{ - int rv = EC_SUCCESS; - - if (argc != 1) - return EC_ERROR_PARAM_COUNT; - - rv = bq27621_probe(); - - return rv; -} - -DECLARE_CONSOLE_COMMAND(fgprobe, command_fgprobe, - "", - "Probe the fg"); - -static int command_fgrd(int argc, char **argv) -{ - int cmd, len; - int rv = EC_SUCCESS; - int data; - char *e; - - if (argc < 3) - return EC_ERROR_PARAM_COUNT; - - cmd = strtoi(argv[1], &e, 0); - if (*e) - return EC_ERROR_PARAM1; - - len = strtoi(argv[2], &e, 0); - if (*e) - return EC_ERROR_PARAM2; - - if (len == 2) - rv = bq27621_read(cmd, &data); - else if (len == 1) - rv = bq27621_read8(cmd, &data); - else - return EC_ERROR_PARAM2; - - CPRINTF("Read %d bytes @0xaa %0x: 0x%0x\n", len, cmd, data); - - return rv; -} - -DECLARE_CONSOLE_COMMAND(fgrd, command_fgrd, - "cmd len", - "Read _len_ words from the fg"); - -static int command_fgcmd(int argc, char **argv) -{ - int cmd, data, byte = 0; - char *e; - - if (argc < 3 || argc > 4) - return EC_ERROR_PARAM_COUNT; - - cmd = strtoi(argv[1], &e, 0); - if (*e) - return EC_ERROR_PARAM1; - - data = strtoi(argv[2], &e, 0); - if (*e) - return EC_ERROR_PARAM2; - - if (argc >= 4) { - byte = strtoi(argv[3], &e, 0); - if (*e) - return EC_ERROR_PARAM3; - } - - if (byte) { - CPRINTF("Write a byte @0xaa %0x: 0x%0x\n", cmd, data); - return bq27621_write8(cmd, data); - } else { - CPRINTF("Write 2 bytes @0xaa %0x: 0x%0x\n", cmd, data); - return bq27621_write(cmd, data); - } - -} - -DECLARE_CONSOLE_COMMAND(fgcmd, command_fgcmd, - "cmd data [byte]", - "Send a cmd to the fg"); - -static int command_fgcmdrd(int argc, char **argv) -{ - int cmd, data, val; - int rv = EC_SUCCESS; - char *e; - - if (argc < 3) - return EC_ERROR_PARAM_COUNT; - - cmd = strtoi(argv[1], &e, 0); - if (*e) - return EC_ERROR_PARAM1; - - data = strtoi(argv[2], &e, 0); - if (*e) - return EC_ERROR_PARAM2; - - rv = bq27621_write(cmd, data); - rv |= bq27621_read(cmd, &val); - - CPRINTF("Read: @0xaa (%x %x) %x\n", cmd, data, val); - return rv; -} - -DECLARE_CONSOLE_COMMAND(fgcmdrd, command_fgcmdrd, - "cmd data", - "Send a 2-byte cmd to the fg, read back the 2-byte result"); - -#endif /* CONFIG_CMD_BATDEBUG */ - diff --git a/driver/battery/bq4050.c b/driver/battery/bq4050.c deleted file mode 100644 index 684ade47e6..0000000000 --- a/driver/battery/bq4050.c +++ /dev/null @@ -1,39 +0,0 @@ -/* Copyright 2018 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. - * - * Smart battery driver for TI BQ4050 family, including BQ40Z50 (and -R1, -R2), - * BQ40Z552, and BQ40Z60. - */ - -#include "battery_smart.h" -#include "util.h" - -#include <stdint.h> - -int battery_bq4050_imbalance_mv(void) -{ - /* - * The BQ4050 family can manage up to four cells. In testing it always - * returns a voltage for each cell, regardless of the number of cells - * actually installed in the pack. Unpopulated cells read exactly zero. - */ - static const uint8_t cell_voltage_address[4] = { - 0x3c, 0x3d, 0x3e, 0x3f - }; - int i, res, cell_voltage; - int n_cells = 0; - int max_voltage = 0; - int min_voltage = 0xffff; - - for (i = 0; i != ARRAY_SIZE(cell_voltage_address); ++i) { - res = sb_read(cell_voltage_address[i], &cell_voltage); - if (res == EC_SUCCESS && cell_voltage != 0) { - n_cells++; - max_voltage = MAX(max_voltage, cell_voltage); - min_voltage = MIN(min_voltage, cell_voltage); - } - } - return (n_cells == 0) ? 0 : max_voltage - min_voltage; -} - diff --git a/driver/battery/max17055.c b/driver/battery/max17055.c deleted file mode 100644 index 35fd63b445..0000000000 --- a/driver/battery/max17055.c +++ /dev/null @@ -1,687 +0,0 @@ -/* Copyright 2017 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. - * - * Battery driver for MAX17055. - */ - -#include "battery.h" -#include "console.h" -#include "extpower.h" -#include "hooks.h" -#include "i2c.h" -#include "max17055.h" -#include "printf.h" -#include "timer.h" -#include "util.h" - -/* Console output macros */ -#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ## args) - -/* - * For max17055 to finish battery presence detection, this is the minimal time - * we have to wait since the last POR. LSB = 175ms. - */ -#define RELIABLE_BATT_DETECT_TIME 0x10 - -/* - * Convert the register values to the units that match - * smart battery protocol. - */ - -/* Voltage reg value to mV */ -#define VOLTAGE_CONV(REG) ((REG * 5) >> 6) -/* Current reg value to mA */ -#define CURRENT_CONV(REG) (((REG * 25) >> 4) / BATTERY_MAX17055_RSENSE) -/* Capacity reg value to mAh */ -#define CAPACITY_CONV(REG) (REG * 5 / BATTERY_MAX17055_RSENSE) -/* Time reg value to minute */ -#define TIME_CONV(REG) ((REG * 3) >> 5) -/* Temperature reg value to 0.1K */ -#define TEMPERATURE_CONV(REG) (((REG * 10) >> 8) + 2731) -/* Percentage reg value to 1% */ -#define PERCENTAGE_CONV(REG) (REG >> 8) -/* Cycle count reg value (LSB = 1%) to absolute count (100%) */ -#define CYCLE_COUNT_CONV(REG) ((REG * 5) >> 9) - -/* Useful macros */ -#define MAX17055_READ_DEBUG(offset, ptr_reg) \ - do { \ - if (max17055_read(offset, ptr_reg)) { \ - CPRINTS("%s: failed to read reg %02x", \ - __func__, offset); \ - return; \ - } \ - } while (0) -#define MAX17055_WRITE_DEBUG(offset, reg) \ - do { \ - if (max17055_write(offset, reg)) { \ - CPRINTS("%s: failed to read reg %02x", \ - __func__, offset); \ - return; \ - } \ - } while (0) - -static int fake_state_of_charge = -1; - -static int max17055_read(int offset, int *data) -{ - return i2c_read16(I2C_PORT_BATTERY, MAX17055_ADDR_FLAGS, - offset, data); -} - -static int max17055_write(int offset, int data) -{ - return i2c_write16(I2C_PORT_BATTERY, MAX17055_ADDR_FLAGS, - offset, data); -} - -/* Return 1 if the device id is correct. */ -static int max17055_probe(void) -{ - int dev_id; - - if (max17055_read(REG_DEVICE_NAME, &dev_id)) - return 0; - if (dev_id == MAX17055_DEVICE_ID) - return 1; - return 0; -} - -int battery_device_name(char *device_name, int buf_size) -{ - int dev_id; - int rv; - - rv = max17055_read(REG_DEVICE_NAME, &dev_id); - if (!rv) - snprintf(device_name, buf_size, "0x%04x", dev_id); - - return rv; -} - -int battery_state_of_charge_abs(int *percent) -{ - return EC_ERROR_UNIMPLEMENTED; -} - -int battery_remaining_capacity(int *capacity) -{ - int rv; - int reg; - - rv = max17055_read(REG_REMAINING_CAPACITY, ®); - if (!rv) - *capacity = CAPACITY_CONV(reg); - return rv; -} - -int battery_full_charge_capacity(int *capacity) -{ - int rv; - int reg; - - rv = max17055_read(REG_FULL_CHARGE_CAPACITY, ®); - if (!rv) - *capacity = CAPACITY_CONV(reg); - return rv; -} - -int battery_time_to_empty(int *minutes) -{ - int rv; - int reg; - - rv = max17055_read(REG_TIME_TO_EMPTY, ®); - if (!rv) - *minutes = TIME_CONV(reg); - return rv; -} - -int battery_time_to_full(int *minutes) -{ - int rv; - int reg; - - rv = max17055_read(REG_TIME_TO_FULL, ®); - if (!rv) - *minutes = TIME_CONV(reg); - return rv; -} - -int battery_cycle_count(int *count) -{ - int rv; - int reg; - - rv = max17055_read(REG_CYCLE_COUNT, ®); - if (!rv) - *count = CYCLE_COUNT_CONV(reg); - return rv; -} - -int battery_design_capacity(int *capacity) -{ - int rv; - int reg; - - rv = max17055_read(REG_DESIGN_CAPACITY, ®); - if (!rv) - *capacity = CAPACITY_CONV(reg); - return rv; -} - -int battery_time_at_rate(int rate, int *minutes) -{ - return EC_ERROR_UNIMPLEMENTED; -} - -int battery_device_chemistry(char *dest, int size) -{ - strzcpy(dest, "<unkn>", size); - - return EC_SUCCESS; -} - -int battery_serial_number(int *serial) -{ - /* TODO(philipchen): Implement this function. */ - *serial = 0xFFFFFFFF; - return EC_SUCCESS; -} - -int battery_design_voltage(int *voltage) -{ - *voltage = battery_get_info()->voltage_normal; - - return EC_SUCCESS; -} - -int battery_get_mode(int *mode) -{ - return EC_ERROR_UNIMPLEMENTED; -} - -int battery_status(int *status) -{ - int rv; - int reg; - - *status = 0; - - rv = max17055_read(REG_FSTAT, ®); - if (rv) - return rv; - if (reg & FSTAT_FQ) - *status |= BATTERY_FULLY_CHARGED; - - rv = max17055_read(REG_AVERAGE_CURRENT, ®); - if (rv) - return rv; - if (reg >> 15) - *status |= BATTERY_DISCHARGING; - - return EC_SUCCESS; -} - -enum battery_present battery_is_present(void) -{ - int reg = 0; - static uint8_t batt_pres_sure; - - if (max17055_read(REG_STATUS, ®)) - return BP_NOT_SURE; - - if (reg & STATUS_BST) - return BP_NO; - - if (!batt_pres_sure) { - /* - * The battery detection result is not reliable within - * ~2.8 secs since POR. - */ - if (!max17055_read(REG_TIMERH, ®)) { - /* - * The LSB of TIMERH reg is 3.2 hrs. If the reg has a - * nonzero value, battery detection must have been - * settled. - */ - if (reg) { - batt_pres_sure = 1; - return BP_YES; - } - if (!max17055_read(REG_TIMER, ®) && - ((uint32_t)reg > RELIABLE_BATT_DETECT_TIME)) { - batt_pres_sure = 1; - return BP_YES; - } - } - return BP_NOT_SURE; - } - return BP_YES; -} - -void battery_get_params(struct batt_params *batt) -{ - int reg = 0; - struct batt_params batt_new = {0}; - - /* - * Assuming the battery is responsive as long as - * max17055 finds battery is present. - */ - batt_new.is_present = battery_is_present(); - - if (batt_new.is_present == BP_YES) - batt_new.flags |= BATT_FLAG_RESPONSIVE; - else if (batt_new.is_present == BP_NO) - /* Battery is not present, gauge won't report useful info. */ - goto batt_out; - - if (max17055_read(REG_TEMPERATURE, ®)) - batt_new.flags |= BATT_FLAG_BAD_TEMPERATURE; - - batt_new.temperature = TEMPERATURE_CONV((int16_t)reg); - - if (max17055_read(REG_STATE_OF_CHARGE, ®) && - fake_state_of_charge < 0) - batt_new.flags |= BATT_FLAG_BAD_STATE_OF_CHARGE; - - batt_new.state_of_charge = fake_state_of_charge >= 0 ? - fake_state_of_charge : PERCENTAGE_CONV(reg); - - if (max17055_read(REG_VOLTAGE, ®)) - batt_new.flags |= BATT_FLAG_BAD_VOLTAGE; - - batt_new.voltage = VOLTAGE_CONV(reg); - - if (max17055_read(REG_AVERAGE_CURRENT, ®)) - batt_new.flags |= BATT_FLAG_BAD_CURRENT; - - batt_new.current = CURRENT_CONV((int16_t)reg); - - batt_new.desired_voltage = battery_get_info()->voltage_max; - batt_new.desired_current = BATTERY_DESIRED_CHARGING_CURRENT; - - if (battery_remaining_capacity(&batt_new.remaining_capacity)) - batt_new.flags |= BATT_FLAG_BAD_REMAINING_CAPACITY; - - if (battery_full_charge_capacity(&batt_new.full_capacity)) - batt_new.flags |= BATT_FLAG_BAD_FULL_CAPACITY; - - /* - * Charging allowed if both desired voltage and current are nonzero - * and battery isn't full (and we read them all correctly). - */ - if (!(batt_new.flags & BATT_FLAG_BAD_STATE_OF_CHARGE) && - batt_new.desired_voltage && - batt_new.desired_current && - batt_new.state_of_charge < BATTERY_LEVEL_FULL) - batt_new.flags |= BATT_FLAG_WANT_CHARGE; - - if (battery_status(&batt_new.status)) - batt_new.flags |= BATT_FLAG_BAD_STATUS; - -batt_out: - /* Update visible battery parameters */ - memcpy(batt, &batt_new, sizeof(*batt)); -} - -#ifdef CONFIG_CMD_PWR_AVG -int battery_get_avg_current(void) -{ - /* TODO(crbug.com/752320) implement this */ - return EC_ERROR_UNIMPLEMENTED; -} - -int battery_get_avg_voltage(void) -{ - /* TODO(crbug.com/752320) implement this */ - return -EC_ERROR_UNIMPLEMENTED; -} -#endif /* CONFIG_CMD_PWR_AVG */ - -/* Wait until battery is totally stable. */ -int battery_wait_for_stable(void) -{ - /* TODO(philipchen): Implement this function. */ - return EC_SUCCESS; -} - -static int max17055_poll_flag_clear(int regno, int mask, int timeout) -{ - int reg; - - do { - if (max17055_read(regno, ®)) - return EC_ERROR_UNKNOWN; - - if (!(mask & reg)) - return EC_SUCCESS; - - msleep(10); - timeout -= 10; - } while (timeout > 0); - - return EC_ERROR_TIMEOUT; -} - -static int max17055_load_ocv_table(const struct max17055_batt_profile *config) -{ - int i; - int reg; - int retries = 3; - - /* Unlock ocv table */ - if (max17055_write(REG_LOCK1, 0x0059) || - max17055_write(REG_LOCK2, 0x00c4)) - return EC_ERROR_UNKNOWN; - - ASSERT(config->ocv_table); - - /* Write ocv data */ - for (i = 0; i < MAX17055_OCV_TABLE_SIZE; i++) { - if (max17055_write(REG_OCV_TABLE_START + i, - config->ocv_table[i])) - return EC_ERROR_UNKNOWN; - } - - /* Read and compare ocv data */ - for (i = 0; i < MAX17055_OCV_TABLE_SIZE; i++) { - if (max17055_read(REG_OCV_TABLE_START + i, ®) || - reg != config->ocv_table[i]) - return EC_ERROR_UNKNOWN; - } - - while (--retries) { - /* Lock ocv table */ - if (max17055_write(REG_LOCK1, 0x0000) || - max17055_write(REG_LOCK2, 0x0000)) - return EC_ERROR_UNKNOWN; - - /* - * If the ocv table remains unlocked, the MAX17055 cannot - * monitor the capacity of the battery. Therefore, it is very - * critical that the ocv table is locked. To verify it is - * locked, simply read back the values. However, this time, - * all values should be read as 0x0000. - */ - for (i = 0; i < MAX17055_OCV_TABLE_SIZE; i++) { - reg = 0xff; - if (max17055_read(REG_OCV_TABLE_START + i, ®)) - return EC_ERROR_UNKNOWN; - if (reg) - break; - } - if (i == MAX17055_OCV_TABLE_SIZE) - break; - msleep(20); - } - if (!retries) - return EC_ERROR_TIMEOUT; - - /* - * Delay 180ms is to prepare the environment to load the custom - * battery parameters. Otherwise, the initialization operation - * has a very small probability of failure. - */ - msleep(180); - - return EC_SUCCESS; -} - -static int max17055_exit_hibernate(void) -{ - /* - * Write REG_COMMAND with 0x90 to force the firmware to stop running. - * Write REG_HIBCFG with 0x00 to exit hibernate mode immediately. - * Write REG_COMMAND with 0x00 to run the firmware again. - */ - if (max17055_write(REG_COMMAND, 0x90) || - max17055_write(REG_HIBCFG, 0x00) || - max17055_write(REG_COMMAND, 0x00)) - return EC_ERROR_UNKNOWN; - - return EC_SUCCESS; -} - -/* Configured MAX17055 with the battery parameters for full model. */ -static int max17055_load_batt_model_full(void) -{ - int reg; - int hib_cfg; - - const struct max17055_batt_profile *config; - - config = max17055_get_batt_profile(); - - /* Store the original HibCFG value. */ - if (max17055_read(REG_HIBCFG, &hib_cfg)) - return EC_ERROR_UNKNOWN; - - /* Force exit from hibernate */ - if (max17055_exit_hibernate()) - return EC_ERROR_UNKNOWN; - - /* Write LearnCFG with LS 7 */ - if (max17055_write(REG_LEARNCFG, config->learn_cfg | 0x0070)) - return EC_ERROR_UNKNOWN; - - /* - * Unlock ocv table access, write/compare/verify custom ocv table, - * lock ocv table access. - */ - if (max17055_load_ocv_table(config)) - return EC_ERROR_UNKNOWN; - - /* Write custom parameters */ - if (max17055_write(REG_DESIGN_CAPACITY, config->design_cap) || - max17055_write(REG_DQACC, config->design_cap >> 4) || - max17055_write(REG_DPACC, 0x0c80) || - max17055_write(REG_CHARGE_TERM_CURRENT, config->ichg_term) || - max17055_write(REG_EMPTY_VOLTAGE, config->v_empty_detect)) - return EC_ERROR_UNKNOWN; - - if (max17055_write(REG_RCOMP0, config->rcomp0) || - max17055_write(REG_TEMPCO, config->tempco) || - max17055_write(REG_QR_TABLE00, config->qr_table00) || - max17055_write(REG_QR_TABLE10, config->qr_table10)) - return EC_ERROR_UNKNOWN; - - /* Update required capacity registers */ - if (max17055_write(REG_REMAINING_CAPACITY, 0x0000) || - max17055_read(REG_VFSOC, ®)) - return EC_ERROR_UNKNOWN; - - if (max17055_write(REG_VFSOC0, reg) || - max17055_write(REG_FULL_CHARGE_CAPACITY, config->design_cap) || - max17055_write(REG_FULLCAPNOM, config->design_cap)) - return EC_ERROR_UNKNOWN; - - /* Prepare to Load Model */ - if (max17055_write(REG_REMAINING_CAPACITY, 0x0000) || - max17055_write(REG_MIXCAP, config->design_cap)) - return EC_ERROR_UNKNOWN; - - /* Initiate model loading */ - if (max17055_read(REG_CONFIG2, ®) || - max17055_write(REG_CONFIG2, reg | CONFIG2_LDMDL)) - return EC_ERROR_UNKNOWN; - - if (max17055_poll_flag_clear(REG_CONFIG2, CONFIG2_LDMDL, 500)) - return EC_ERROR_UNKNOWN; - - /* Write LearnCFG with LS 0 */ - if (max17055_write(REG_LEARNCFG, config->learn_cfg & 0xff8f) || - max17055_write(REG_QR_TABLE20, config->qr_table20) || - max17055_write(REG_QR_TABLE30, config->qr_table30)) - return EC_ERROR_UNKNOWN; - - /* Restore the original HibCFG value. */ - if (max17055_write(REG_HIBCFG, hib_cfg)) - return EC_ERROR_UNKNOWN; - - return EC_SUCCESS; -} - -/* - * Configured MAX17055 with the battery parameters for short model or ez model - */ -static int max17055_load_batt_model_short_or_ez(void) -{ - int hib_cfg; - int dqacc; - int dpacc; - - const struct max17055_batt_profile *config; - - config = max17055_get_batt_profile(); - - if (config->is_ez_config) { - dqacc = config->design_cap / 32; - /* Choose the model for charge voltage > 4.275V. */ - dpacc = dqacc * 51200 / config->design_cap; - } else { - dqacc = config->design_cap / 16; - dpacc = config->dpacc; - } - - if (max17055_write(REG_DESIGN_CAPACITY, config->design_cap) || - max17055_write(REG_DQACC, dqacc) || - max17055_write(REG_CHARGE_TERM_CURRENT, config->ichg_term) || - max17055_write(REG_EMPTY_VOLTAGE, config->v_empty_detect)) - return EC_ERROR_UNKNOWN; - - if (!config->is_ez_config) { - if (max17055_write(REG_LEARNCFG, config->learn_cfg)) - return EC_ERROR_UNKNOWN; - } - - /* Store the original HibCFG value. */ - if (max17055_read(REG_HIBCFG, &hib_cfg)) - return EC_ERROR_UNKNOWN; - - /* Force exit from hibernate */ - if (max17055_exit_hibernate()) - return EC_ERROR_UNKNOWN; - - if (max17055_write(REG_DPACC, dpacc) || - max17055_write(REG_MODELCFG, (MODELCFG_REFRESH | MODELCFG_VCHG))) - return EC_ERROR_UNKNOWN; - - /* Delay up to 500 ms until MODELCFG.REFRESH bit == 0. */ - if (max17055_poll_flag_clear(REG_MODELCFG, MODELCFG_REFRESH, 500)) - return EC_ERROR_UNKNOWN; - - if (!config->is_ez_config) { - if (max17055_write(REG_RCOMP0, config->rcomp0) || - max17055_write(REG_TEMPCO, config->tempco) || - max17055_write(REG_QR_TABLE00, config->qr_table00) || - max17055_write(REG_QR_TABLE10, config->qr_table10) || - max17055_write(REG_QR_TABLE20, config->qr_table20) || - max17055_write(REG_QR_TABLE30, config->qr_table30)) - return EC_ERROR_UNKNOWN; - } - - /* Restore the original HibCFG value. */ - if (max17055_write(REG_HIBCFG, hib_cfg)) - return EC_ERROR_UNKNOWN; - return EC_SUCCESS; -} - -static int max17055_load_batt_model(void) -{ - if (IS_ENABLED(CONFIG_BATTERY_MAX17055_FULL_MODEL)) - return max17055_load_batt_model_full(); - else - return max17055_load_batt_model_short_or_ez(); -} - -static void max17055_init(void) -{ - int reg; - int retries = 80; -#ifdef CONFIG_BATTERY_MAX17055_ALERT - const struct max17055_alert_profile *alert_profile = - max17055_get_alert_profile(); -#endif - - if (!max17055_probe()) { - CPRINTS("Wrong max17055 id!"); - return; - } - - /* - * Set CONFIG.TSEL to measure temperature using external thermistor. - * Set it as early as possible because max17055 takes up to 1000ms to - * have the first reliable external temperature reading. - */ - MAX17055_READ_DEBUG(REG_CONFIG, ®); - MAX17055_WRITE_DEBUG(REG_CONFIG, (reg | CONF_TSEL)); - - MAX17055_READ_DEBUG(REG_STATUS, ®); - - /* Check for POR */ - if (STATUS_POR & reg) { - /* Delay up to 800 ms until FSTAT.DNR bit == 0. */ - while (--retries) { - MAX17055_READ_DEBUG(REG_FSTAT, ®); - if (!(FSTAT_DNR & reg)) - break; - msleep(10); - } - if (!retries) { - CPRINTS("%s: timeout waiting for FSTAT.DNR cleared", - __func__); - return; - } - - if (max17055_load_batt_model()) { - CPRINTS("max17055 configuration failed!"); - return; - } - - /* Clear POR bit */ - MAX17055_READ_DEBUG(REG_STATUS, ®); - MAX17055_WRITE_DEBUG(REG_STATUS, (reg & ~STATUS_POR)); - } else { - const struct max17055_batt_profile *config; - - config = max17055_get_batt_profile(); - MAX17055_READ_DEBUG(REG_DESIGN_CAPACITY, ®); - - /* - * Reload the battery model if the current running one - * is wrong. - */ - if (config->design_cap != reg) { - CPRINTS("max17055 reconfig..."); - if (max17055_load_batt_model()) { - CPRINTS("max17055 configuration failed!"); - return; - } - } - } - -#ifdef CONFIG_BATTERY_MAX17055_ALERT - /* Set voltage alert range */ - MAX17055_WRITE_DEBUG(REG_VALRTTH, alert_profile->v_alert_mxmn); - /* Set temperature alert range */ - MAX17055_WRITE_DEBUG(REG_TALRTTH, alert_profile->t_alert_mxmn); - /* Set state-of-charge alert range */ - MAX17055_WRITE_DEBUG(REG_SALRTTH, alert_profile->s_alert_mxmn); - /* Set current alert range */ - MAX17055_WRITE_DEBUG(REG_IALRTTH, alert_profile->i_alert_mxmn); - - /* Disable all sticky bits; enable alert AEN */ - MAX17055_READ_DEBUG(REG_CONFIG, ®); - MAX17055_WRITE_DEBUG(REG_CONFIG, (reg & ~CONF_ALL_STICKY) | CONF_AEN); - - /* Clear alerts */ - MAX17055_READ_DEBUG(REG_STATUS, ®); - MAX17055_WRITE_DEBUG(REG_STATUS, reg & ~STATUS_ALL_ALRT); -#endif - - CPRINTS("max17055 configuration succeeded!"); -} -DECLARE_HOOK(HOOK_INIT, max17055_init, HOOK_PRIO_DEFAULT); diff --git a/driver/battery/max17055.h b/driver/battery/max17055.h deleted file mode 100644 index 0f97fb90f0..0000000000 --- a/driver/battery/max17055.h +++ /dev/null @@ -1,250 +0,0 @@ -/* Copyright 2017 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. - * - * Battery driver for MAX17055. - */ - -#ifndef __CROS_EC_MAX17055_H -#define __CROS_EC_MAX17055_H - -#define MAX17055_ADDR_FLAGS 0x36 -#define MAX17055_DEVICE_ID 0x4010 -#define MAX17055_OCV_TABLE_SIZE 48 - -#define REG_STATUS 0x00 -#define REG_VALRTTH 0x01 -#define REG_TALRTTH 0x02 -#define REG_SALRTTH 0x03 -#define REG_AT_RATE 0x04 -#define REG_REMAINING_CAPACITY 0x05 -#define REG_STATE_OF_CHARGE 0x06 -#define REG_TEMPERATURE 0x08 -#define REG_VOLTAGE 0x09 -#define REG_CURRENT 0x0a -#define REG_AVERAGE_CURRENT 0x0b -#define REG_MIXCAP 0x0f -#define REG_FULL_CHARGE_CAPACITY 0x10 -#define REG_TIME_TO_EMPTY 0x11 -#define REG_QR_TABLE00 0x12 -#define REG_CONFIG 0x1D -#define REG_AVERAGE_TEMPERATURE 0x16 -#define REG_CYCLE_COUNT 0x17 -#define REG_DESIGN_CAPACITY 0x18 -#define REG_AVERAGE_VOLTAGE 0x19 -#define REG_MAX_MIN_TEMP 0x1a -#define REG_MAX_MIN_VOLT 0x1b -#define REG_MAX_MIN_CURR 0x1c -#define REG_CHARGE_TERM_CURRENT 0x1e -#define REG_TIME_TO_FULL 0x20 -#define REG_DEVICE_NAME 0x21 -#define REG_QR_TABLE10 0x22 -#define REG_FULLCAPNOM 0x23 -#define REG_LEARNCFG 0x28 -#define REG_QR_TABLE20 0x32 -#define REG_RCOMP0 0x38 -#define REG_TEMPCO 0x39 -#define REG_EMPTY_VOLTAGE 0x3a -#define REG_FSTAT 0x3d -#define REG_TIMER 0x3e -#define REG_QR_TABLE30 0x42 -#define REG_DQACC 0x45 -#define REG_DPACC 0x46 -#define REG_VFSOC0 0x48 -#define REG_COMMAND 0x60 -#define REG_LOCK1 0x62 -#define REG_LOCK2 0x63 -#define REG_OCV_TABLE_START 0x80 -#define REG_STATUS2 0xb0 -#define REG_IALRTTH 0xb4 -#define REG_HIBCFG 0xba -#define REG_CONFIG2 0xbb -#define REG_TIMERH 0xbe -#define REG_MODELCFG 0xdb -#define REG_VFSOC 0xff - -/* Status reg (0x00) flags */ -#define STATUS_POR BIT(1) -#define STATUS_IMN BIT(2) -#define STATUS_BST BIT(3) -#define STATUS_IMX BIT(6) -#define STATUS_VMN BIT(8) -#define STATUS_TMN BIT(9) -#define STATUS_SMN BIT(10) -#define STATUS_VMX BIT(12) -#define STATUS_TMX BIT(13) -#define STATUS_SMX BIT(14) -#define STATUS_ALL_ALRT \ - (STATUS_IMN | STATUS_IMX | STATUS_VMN | STATUS_VMX | STATUS_TMN | \ - STATUS_TMX | STATUS_SMN | STATUS_SMX) - -/* Alert disable values (0x01, 0x02, 0x03, 0xb4) */ -#define VALRT_DISABLE 0xff00 -#define TALRT_DISABLE 0x7f80 -#define SALRT_DISABLE 0xff00 -#define IALRT_DISABLE 0x7f80 - -/* Config reg (0x1d) flags */ -#define CONF_AEN BIT(2) -#define CONF_IS BIT(11) -#define CONF_VS BIT(12) -#define CONF_TS BIT(13) -#define CONF_SS BIT(14) -#define CONF_TSEL BIT(15) -#define CONF_ALL_STICKY (CONF_IS | CONF_VS | CONF_TS | CONF_SS) - -/* FStat reg (0x3d) flags */ -#define FSTAT_DNR 0x0001 -#define FSTAT_FQ 0x0080 - -/* Config2 reg (0xbb) flags */ -#define CONFIG2_LDMDL BIT(5) - -/* ModelCfg reg (0xdb) flags */ -#define MODELCFG_REFRESH BIT(15) -#define MODELCFG_VCHG BIT(10) - -/* Smart battery status bits (sbs reg 0x16) */ -#define BATTERY_DISCHARGING 0x40 -#define BATTERY_FULLY_CHARGED 0x20 - -/* - * Before we have the battery fully characterized, we use these macros to - * convert basic battery parameters to max17055 reg values for ez config. - */ - -/* Convert design capacity in mAh to max17055 0x18 reg value */ -#define MAX17055_DESIGNCAP_REG(bat_cap_mah) \ - (bat_cap_mah * BATTERY_MAX17055_RSENSE / 5) -/* Convert charge termination current in mA to max17055 0x1e reg value */ -#define MAX17055_ICHGTERM_REG(term_cur_ma) \ - (((term_cur_ma * BATTERY_MAX17055_RSENSE) << 4) / 25) -/* - * This macro converts empty voltage target (VE) and recovery voltage (VR) - * in mV to max17055 0x3a reg value. max17055 declares 0% (empty battery) at - * VE. max17055 reenables empty detection when the cell voltage rises above VR. - * VE ranges from 0 to 5110mV, and VR ranges from 0 to 5080mV. - */ -#define MAX17055_VEMPTY_REG(ve_mv, vr_mv) \ - (((ve_mv / 10) << 7) | (vr_mv / 40)) - -#define MAX17055_MAX_MIN_REG(mx, mn) ((((int16_t)(mx)) << 8) | ((mn))) -/* Converts voltages alert range for VALRTTH_REG */ -#define MAX17055_VALRTTH_RESOLUTION 20 -#define MAX17055_VALRTTH_REG(mx, mn) \ - MAX17055_MAX_MIN_REG((uint8_t)(mx / MAX17055_VALRTTH_RESOLUTION), \ - (uint8_t)(mn / MAX17055_VALRTTH_RESOLUTION)) -/* Converts temperature alert range for TALRTTH_REG */ -#define MAX17055_TALRTTH_REG(mx, mn) \ - MAX17055_MAX_MIN_REG((int8_t)(mx), (int8_t)(mn)) -/* Converts state-of-charge alert range for SALRTTH_REG */ -#define MAX17055_SALRTTH_REG(mx, mn) \ - MAX17055_MAX_MIN_REG((uint8_t)(mx), (uint8_t)(mn)) -/* Converts current alert range for IALRTTH_REG */ -/* Current resolution: 0.4mV/RSENSE */ -#define MAX17055_IALRTTH_MUL (10 * BATTERY_MAX17055_RSENSE) -#define MAX17055_IALRTTH_DIV 4 -#define MAX17055_IALRTTH_REG(mx, mn) \ - MAX17055_MAX_MIN_REG( \ - (int8_t)(mx * MAX17055_IALRTTH_MUL / MAX17055_IALRTTH_DIV), \ - (int8_t)(mn * MAX17055_IALRTTH_MUL / MAX17055_IALRTTH_DIV)) - -/* - * max17055 needs some special battery parameters for fuel gauge - * learning algorithm. Maxim can help characterize the battery pack - * to get a full parameter list. We create a data structure to store - * the battery parameters in the format of max17055 register values. - */ -struct max17055_batt_profile { - /* Design capacity of the cell (LSB = 5uVH / Rsense) */ - uint16_t design_cap; - /* Charge termination current (LSB = 1.5625uV / Rsense) */ - uint16_t ichg_term; - /* The combination of empty voltage target and recovery voltage */ - uint16_t v_empty_detect; - - /* - * The parameters below are used for advanced (non-EZ) config - * (dpacc, learn_cfg, tempco, qr_table00, qr_table10, - * qr_table20, and qr_table30) - */ - - /* Change in battery SOC between relaxation points (LSB = pct / 16) */ - uint16_t dpacc; - /* Magic cell tuning parameters */ - uint16_t learn_cfg; - uint16_t rcomp0; - uint16_t tempco; - uint16_t qr_table00; - uint16_t qr_table10; - uint16_t qr_table20; - uint16_t qr_table30; - - /* - * If is_ez_config is nonzero, we only use design_cap, ichg_term, - * and v_empty_detect to config max17055 (a.k.a. EZ-config). - */ - uint8_t is_ez_config; - - /* Used only for full model */ - const uint16_t *ocv_table; -}; - -/* Return the special battery parameters max17055 needs. */ -const struct max17055_batt_profile *max17055_get_batt_profile(void); - -#ifdef CONFIG_BATTERY_MAX17055_ALERT -/* - * max17055 supports alert on voltage, current, state-of-charge, and - * temperature. To enable this feature, the information of the limit range is - * needed. - */ -struct max17055_alert_profile { - /* - * Sets voltage upper and lower limits that generate an alert if - * voltage is outside of the v_alert_mxmn range. - * The upper 8 bits set the maximum value and the lower 8 bits set the - * minimum value. Interrupt threshold limits are selectable with 20mV - * resolution. - * Use MAX17055_VALRTTH_REG(max, min) to setup the desired range, - * VALRT_DISABLE to disable the alert. - */ - const uint16_t v_alert_mxmn; - /* - * Sets temperature upper and lower limits that generate an alert if - * temperature is outside of the t_alert_mxmn range. - * The upper 8 bits set the maximum value and the lower 8 bits set the - * minimum value. Interrupt threshold limits are stored in - * 2’s-complement format with 1°C resolution. - * Use MAX17055_TALRTTH_REG(max, min) to setup the desired range, - * TALRT_DISABLE to disable the alert. - */ - const uint16_t t_alert_mxmn; - /* - * Sets reported state-of-charge upper and lower limits that generate - * an alert if SOC is outside of the s_alert_mxmn range. - * The upper 8 bits set the maximum value and the lower 8 bits set the - * minimum value. Interrupt threshold limits are configurable with 1% - * resolution. - * Use MAX17055_SALRTTH_REG(max, min) to setup the desired range, - * SALRT_DISABLE to disable the alert. - */ - const uint16_t s_alert_mxmn; - /* - * Sets current upper and lower limits that generate an alert if - * current is outside of the i_alert_mxmn range. - * The upper 8 bits set the maximum value and the lower 8 bits set the - * minimum value. Interrupt threshold limits are selectable with - * 0.4mV/R SENSE resolution. - * Use MAX17055_IALRTTH_REG(max, min) to setup the desired range, - * IALRT_DISABLE to disable the alert. - */ - const uint16_t i_alert_mxmn; -}; - -/* - * Return the battery/system's alert threshoulds that max17055 needs. - */ -const struct max17055_alert_profile *max17055_get_alert_profile(void); -#endif /* CONFIG_BATTERY_MAX17055_ALERT */ -#endif /* __CROS_EC_MAX17055_H */ diff --git a/driver/battery/mm8013.c b/driver/battery/mm8013.c deleted file mode 100644 index cd1a2a2083..0000000000 --- a/driver/battery/mm8013.c +++ /dev/null @@ -1,245 +0,0 @@ -/* Copyright 2019 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. - * - * Battery driver for MM8013. - */ - -#include "battery.h" -#include "battery_smart.h" -#include "console.h" -#include "i2c.h" -#include "mm8013.h" -#include "timer.h" -#include "util.h" - -#define BATTERY_PACK_INFO_LENGTH 8 - -/* MM8013 requires a 100us wait time after a read operation. */ -#define I2C_WAIT_TIME 100 - -static int mm8013_read16(int offset, int *data) -{ - int rv; - - *data = 0; - rv = i2c_read16(I2C_PORT_BATTERY, MM8013_ADDR_FLAGS, offset, data); - usleep(I2C_WAIT_TIME); - if (rv) - return rv; - return EC_SUCCESS; -} - -static int mm8013_read_block(int offset, uint8_t *data, int len) -{ - int rv; - - rv = i2c_read_block(I2C_PORT_BATTERY, MM8013_ADDR_FLAGS, - offset, data, len); - usleep(I2C_WAIT_TIME); - if (rv) - return rv; - return EC_SUCCESS; -} - -static int battery_flag(int *flag) -{ - return mm8013_read16(REG_FLAGS, flag); -} - -static int battery_current(int *current) -{ - int16_t tmp; - int rv; - - rv = mm8013_read_block(REG_AVERAGE_CURRENT, - (uint8_t *)&tmp, sizeof(int16_t)); - if (rv) - return rv; - *current = tmp; - - return EC_SUCCESS; -} - -int battery_device_name(char *device_name, int buf_size) -{ - int rv; - char out_buf[BATTERY_PACK_INFO_LENGTH + 1]; - - rv = mm8013_read_block(REG_PRODUCT_INFORMATION, - (uint8_t *)out_buf, BATTERY_PACK_INFO_LENGTH); - if (rv) - return rv; - - out_buf[BATTERY_PACK_INFO_LENGTH] = '\0'; - strzcpy(device_name, out_buf, buf_size); - - return EC_SUCCESS; -} - -int battery_state_of_charge_abs(int *percent) -{ - return mm8013_read16(REG_STATE_OF_CHARGE, percent); -} - -int battery_remaining_capacity(int *capacity) -{ - return mm8013_read16(REG_REMAINING_CAPACITY, capacity); -} - -int battery_full_charge_capacity(int *capacity) -{ - return mm8013_read16(REG_FULL_CHARGE_CAPACITY, capacity); -} - -int battery_time_to_empty(int *minutes) -{ - return mm8013_read16(REG_AVERAGE_TIME_TO_EMPTY, minutes); -} - -int battery_time_to_full(int *minutes) -{ - return mm8013_read16(REG_AVERAGE_TIME_TO_FULL, minutes); -} - -int battery_cycle_count(int *count) -{ - return mm8013_read16(REG_CYCLE_COUNT, count); -} - -int battery_design_capacity(int *capacity) -{ - return mm8013_read16(REG_DESIGN_CAPACITY, capacity); -} - -int battery_time_at_rate(int rate, int *minutes) -{ - return EC_ERROR_UNIMPLEMENTED; -} - -int battery_device_chemistry(char *dest, int size) -{ - strzcpy(dest, "<unkn>", size); - - return EC_SUCCESS; -} - -int battery_serial_number(int *serial) -{ - *serial = 0xFFFFFFFF; - return EC_SUCCESS; -} - -int battery_design_voltage(int *voltage) -{ - *voltage = battery_get_info()->voltage_normal; - - return EC_SUCCESS; -} - -int battery_get_mode(int *mode) -{ - return EC_ERROR_UNIMPLEMENTED; -} - -int battery_status(int *status) -{ - int rv; - int flag = 0; - - *status = 0; - - rv = battery_flag(&flag); - if (rv) - return rv; - - if (flag & (MM8013_FLAG_OTC | MM8013_FLAG_OTD)) - *status |= STATUS_OVERTEMP_ALARM; - if (flag & MM8013_FLAG_FC) - *status |= STATUS_FULLY_CHARGED; - if (flag & MM8013_FLAG_DSG) - *status |= STATUS_DISCHARGING; - if (flag & MM8013_FLAG_BATHI) - *status |= STATUS_OVERCHARGED_ALARM; - - return EC_SUCCESS; -} - -enum battery_present battery_is_present(void) -{ - int temp; - - if (mm8013_read16(REG_TEMPERATURE, &temp)) - return BP_NO; - return BP_YES; -} - -void battery_get_params(struct batt_params *batt) -{ - struct batt_params batt_new = {0}; - int flag = 0; - - /* - * Assuming the battery is responsive as long as - * mm8013 finds battery is present. - */ - batt_new.is_present = battery_is_present(); - - if (batt_new.is_present == BP_YES) - batt_new.flags |= BATT_FLAG_RESPONSIVE; - else if (batt_new.is_present == BP_NO) - /* Battery is not present, gauge won't report useful info. */ - goto batt_out; - - if (mm8013_read16(REG_TEMPERATURE, &batt_new.temperature)) - batt_new.flags |= BATT_FLAG_BAD_TEMPERATURE; - - if (mm8013_read16(REG_STATE_OF_CHARGE, &batt_new.state_of_charge)) - batt_new.flags |= BATT_FLAG_BAD_STATE_OF_CHARGE; - - if (mm8013_read16(REG_VOLTAGE, &batt_new.voltage)) - batt_new.flags |= BATT_FLAG_BAD_VOLTAGE; - - if (battery_current(&batt_new.current)) - batt_new.flags |= BATT_FLAG_BAD_CURRENT; - - batt_new.desired_voltage = battery_get_info()->voltage_max; - batt_new.desired_current = BATTERY_DESIRED_CHARGING_CURRENT; - - if (battery_remaining_capacity(&batt_new.remaining_capacity)) - batt_new.flags |= BATT_FLAG_BAD_REMAINING_CAPACITY; - - if (battery_full_charge_capacity(&batt_new.full_capacity)) - batt_new.flags |= BATT_FLAG_BAD_FULL_CAPACITY; - - if (battery_status(&batt_new.status)) - batt_new.flags |= BATT_FLAG_BAD_STATUS; - - if (!battery_flag(&flag) && (flag & MM8013_FLAG_CHG)) - batt_new.flags |= BATT_FLAG_WANT_CHARGE; - -batt_out: - /* Update visible battery parameters */ - memcpy(batt, &batt_new, sizeof(*batt)); -} - -#ifdef CONFIG_CMD_PWR_AVG -int battery_get_avg_current(void) -{ - /* TODO(crbug.com/752320) implement this */ - return -EC_ERROR_UNIMPLEMENTED; -} - -int battery_get_avg_voltage(void) -{ - /* TODO(crbug.com/752320) implement this */ - return -EC_ERROR_UNIMPLEMENTED; -} -#endif /* CONFIG_CMD_PWR_AVG */ - -/* Wait until battery is totally stable. */ -int battery_wait_for_stable(void) -{ - /* TODO(phoenixshen): Implement this function. */ - return EC_SUCCESS; -} diff --git a/driver/battery/mm8013.h b/driver/battery/mm8013.h deleted file mode 100644 index 2ffaca7b5d..0000000000 --- a/driver/battery/mm8013.h +++ /dev/null @@ -1,40 +0,0 @@ -/* Copyright 2019 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. - * - * Battery driver for MM8013. - */ - -#ifndef __CROS_EC_MM8013_H -#define __CROS_EC_MM8013_H - -#define MM8013_ADDR_FLAGS 0x55 - -#define REG_TEMPERATURE 0x06 -#define REG_VOLTAGE 0x08 -#define REG_FLAGS 0x0a -#define REG_FULL_CHARGE_CAPACITY 0x0e -#define REG_REMAINING_CAPACITY 0x10 -#define REG_AVERAGE_CURRENT 0x14 -#define REG_AVERAGE_TIME_TO_EMPTY 0x16 -#define REG_AVERAGE_TIME_TO_FULL 0x18 -#define REG_STATE_OF_CHARGE 0x2c -#define REG_CYCLE_COUNT 0x2a -#define REG_DESIGN_CAPACITY 0x3c -#define REG_PRODUCT_INFORMATION 0x64 - -/* Over Temperature in charge */ -#define MM8013_FLAG_OTC BIT(15) -/* Over Temperature in discharge */ -#define MM8013_FLAG_OTD BIT(14) -/* Over-charge */ -#define MM8013_FLAG_BATHI BIT(13) -/* Full Charge */ -#define MM8013_FLAG_FC BIT(9) -/* Charge allowed */ -#define MM8013_FLAG_CHG BIT(8) -/* Discharge */ -#define MM8013_FLAG_DSG BIT(0) - - -#endif /* __CROS_EC_MM8013_H */ diff --git a/driver/battery/smart.c b/driver/battery/smart.c deleted file mode 100644 index 14106664cb..0000000000 --- a/driver/battery/smart.c +++ /dev/null @@ -1,676 +0,0 @@ -/* Copyright 2012 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. - * - * Smart battery driver. - */ - -#include "battery.h" -#include "battery_smart.h" -#include "console.h" -#include "host_command.h" -#include "i2c.h" -#include "timer.h" -#include "util.h" - -/* Console output macros */ -#define CPUTS(outstr) cputs(CC_CHARGER, outstr); -#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ## args) - -#define BATTERY_NO_RESPONSE_TIMEOUT (1000*MSEC) - -static int fake_state_of_charge = -1; -static int fake_temperature = -1; - -static int battery_supports_pec(void) -{ - static int supports_pec = -1; - - if (!IS_ENABLED(CONFIG_SMBUS_PEC)) - return 0; - - if (supports_pec < 0) { - int spec_info; - int rv = i2c_read16(I2C_PORT_BATTERY, BATTERY_ADDR_FLAGS, - SB_SPECIFICATION_INFO, &spec_info); - /* failed, assuming not support and try again later */ - if (rv) - return 0; - - supports_pec = (BATTERY_SPEC_VERSION(spec_info) == - BATTERY_SPEC_VER_1_1_WITH_PEC); - CPRINTS("battery supports pec: %d", supports_pec); - } - return supports_pec; -} - -test_mockable int sb_read(int cmd, int *param) -{ - uint16_t addr_flags = BATTERY_ADDR_FLAGS; - -#ifdef CONFIG_BATTERY_CUT_OFF - /* - * Some batteries would wake up after cut-off if we talk to it. - */ - if (battery_is_cut_off()) - return EC_RES_ACCESS_DENIED; -#endif - if (battery_supports_pec()) - addr_flags |= I2C_FLAG_PEC; - - return i2c_read16(I2C_PORT_BATTERY, addr_flags, cmd, param); -} - -test_mockable int sb_write(int cmd, int param) -{ - uint16_t addr_flags = BATTERY_ADDR_FLAGS; - -#ifdef CONFIG_BATTERY_CUT_OFF - /* - * Some batteries would wake up after cut-off if we talk to it. - */ - if (battery_is_cut_off()) - return EC_RES_ACCESS_DENIED; -#endif - if (battery_supports_pec()) - addr_flags |= I2C_FLAG_PEC; - - return i2c_write16(I2C_PORT_BATTERY, addr_flags, cmd, param); -} - -int sb_read_string(int offset, uint8_t *data, int len) -{ - uint16_t addr_flags = BATTERY_ADDR_FLAGS; - -#ifdef CONFIG_BATTERY_CUT_OFF - /* - * Some batteries would wake up after cut-off if we talk to it. - */ - if (battery_is_cut_off()) - return EC_RES_ACCESS_DENIED; -#endif - if (battery_supports_pec()) - addr_flags |= I2C_FLAG_PEC; - - return i2c_read_string(I2C_PORT_BATTERY, addr_flags, offset, data, len); -} - -int sb_read_mfgacc(int cmd, int block, uint8_t *data, int len) -{ - int rv; - - /* - * First two bytes returned from read are command sent hence read - * doesn't yield anything if the length is less than 3 bytes. - */ - if (len < 3) - return EC_ERROR_INVAL; - - /* Send manufacturer access command */ - rv = sb_write(SB_MANUFACTURER_ACCESS, cmd); - if (rv) - return rv; - - /* - * Read data on the register block. - * First two bytes returned are command sent, - * rest are actual data LSB to MSB. - */ - rv = sb_read_string(block, data, len); - if (rv) - return rv; - if ((data[0] | data[1] << 8) != cmd) - return EC_ERROR_UNKNOWN; - - return EC_SUCCESS; -} - -int sb_write_block(int reg, const uint8_t *val, int len) -{ - uint16_t addr_flags = BATTERY_ADDR_FLAGS; - -#ifdef CONFIG_BATTERY_CUT_OFF - /* - * Some batteries would wake up after cut-off if we talk to it. - */ - if (battery_is_cut_off()) - return EC_RES_ACCESS_DENIED; -#endif - - if (battery_supports_pec()) - addr_flags |= I2C_FLAG_PEC; - - /* TODO: implement smbus_write_block. */ - return i2c_write_block(I2C_PORT_BATTERY, addr_flags, reg, val, len); -} - -int battery_get_mode(int *mode) -{ - return sb_read(SB_BATTERY_MODE, mode); -} - -/** - * Force battery to mAh mode (instead of 10mW mode) for reporting capacity. - * - * @return non-zero if error. - */ - -static int battery_force_mah_mode(void) -{ - int val, rv; - rv = battery_get_mode(&val); - if (rv) - return rv; - - if (val & MODE_CAPACITY) - rv = sb_write(SB_BATTERY_MODE, val & ~MODE_CAPACITY); - - return rv; -} - -int battery_state_of_charge_abs(int *percent) -{ - return sb_read(SB_ABSOLUTE_STATE_OF_CHARGE, percent); -} - -int battery_remaining_capacity(int *capacity) -{ - int rv = battery_force_mah_mode(); - if (rv) - return rv; - - return sb_read(SB_REMAINING_CAPACITY, capacity); -} - -int battery_full_charge_capacity(int *capacity) -{ - int rv = battery_force_mah_mode(); - if (rv) - return rv; - - return sb_read(SB_FULL_CHARGE_CAPACITY, capacity); -} - -int battery_time_to_empty(int *minutes) -{ - return sb_read(SB_AVERAGE_TIME_TO_EMPTY, minutes); -} - -int battery_run_time_to_empty(int *minutes) -{ - return sb_read(SB_RUN_TIME_TO_EMPTY, minutes); -} - -int battery_time_to_full(int *minutes) -{ - return sb_read(SB_AVERAGE_TIME_TO_FULL, minutes); -} - -/* Read battery status */ -int battery_status(int *status) -{ - return sb_read(SB_BATTERY_STATUS, status); -} - -/* Battery charge cycle count */ -int battery_cycle_count(int *count) -{ - return sb_read(SB_CYCLE_COUNT, count); -} - -int battery_design_capacity(int *capacity) -{ - int rv = battery_force_mah_mode(); - if (rv) - return rv; - - return sb_read(SB_DESIGN_CAPACITY, capacity); -} - -/* Designed battery output voltage - * unit: mV - */ -int battery_design_voltage(int *voltage) -{ - return sb_read(SB_DESIGN_VOLTAGE, voltage); -} - -/* Read serial number */ -int battery_serial_number(int *serial) -{ - return sb_read(SB_SERIAL_NUMBER, serial); -} - -test_mockable int battery_time_at_rate(int rate, int *minutes) -{ - int rv; - int ok, time; - int loop, cmd, output_sign; - - if (rate == 0) { - *minutes = 0; - return EC_ERROR_INVAL; - } - - rv = sb_write(SB_AT_RATE, rate); - if (rv) - return rv; - loop = 5; - while (loop--) { - rv = sb_read(SB_AT_RATE_OK, &ok); - if (rv) - return rv; - if (ok) { - if (rate > 0) { - cmd = SB_AT_RATE_TIME_TO_FULL; - output_sign = -1; - } else { - cmd = SB_AT_RATE_TIME_TO_EMPTY; - output_sign = 1; - } - rv = sb_read(cmd, &time); - if (rv) - return rv; - - *minutes = (time == 0xffff) ? 0 : output_sign * time; - return EC_SUCCESS; - } else { - /* wait 10ms for AT_RATE_OK */ - msleep(10); - } - } - return EC_ERROR_TIMEOUT; -} - -test_mockable int battery_manufacture_date(int *year, int *month, int *day) -{ - int rv; - int ymd; - - rv = sb_read(SB_SPECIFICATION_INFO, &ymd); - if (rv) - return rv; - - /* battery date format: - * ymd = day + month * 32 + (year - 1980) * 256 - */ - *year = (ymd >> 8) + 1980; - *month = (ymd & 0xff) / 32; - *day = (ymd & 0xff) % 32; - - return EC_SUCCESS; -} - -int get_battery_manufacturer_name(char *dest, int size) -{ - return sb_read_string(SB_MANUFACTURER_NAME, dest, size); -} - -/* Read device name */ -test_mockable int battery_device_name(char *dest, int size) -{ - return sb_read_string(SB_DEVICE_NAME, dest, size); -} - -/* Read battery type/chemistry */ -test_mockable int battery_device_chemistry(char *dest, int size) -{ - return sb_read_string(SB_DEVICE_CHEMISTRY, dest, size); -} - -#ifdef CONFIG_CMD_PWR_AVG -int battery_get_avg_current(void) -{ - int current; - - /* This is a signed 16-bit value. */ - sb_read(SB_AVERAGE_CURRENT, ¤t); - return (int16_t)current; -} - -/* - * Technically returns only the instantaneous reading, but tests showed that - * for the majority of charge states above 3% this varies by less than 40mV - * every minute, so we accept the inaccuracy here. - */ -int battery_get_avg_voltage(void) -{ - int voltage = -EC_ERROR_UNKNOWN; - - sb_read(SB_VOLTAGE, &voltage); - return voltage; -} -#endif /* CONFIG_CMD_PWR_AVG */ - -void battery_get_params(struct batt_params *batt) -{ - struct batt_params batt_new = {0}; - int v; - - if (sb_read(SB_TEMPERATURE, &batt_new.temperature) - && fake_temperature < 0) - batt_new.flags |= BATT_FLAG_BAD_TEMPERATURE; - - /* If temperature is faked, override with faked data */ - if (fake_temperature >= 0) - batt_new.temperature = fake_temperature; - - if (sb_read(SB_RELATIVE_STATE_OF_CHARGE, &batt_new.state_of_charge) - && fake_state_of_charge < 0) - batt_new.flags |= BATT_FLAG_BAD_STATE_OF_CHARGE; - - /* If soc is faked, override with faked data */ - if (fake_state_of_charge >= 0) - batt_new.state_of_charge = fake_state_of_charge; - - if (sb_read(SB_VOLTAGE, &batt_new.voltage)) - batt_new.flags |= BATT_FLAG_BAD_VOLTAGE; - - /* This is a signed 16-bit value. */ - if (sb_read(SB_CURRENT, &v)) - batt_new.flags |= BATT_FLAG_BAD_CURRENT; - else - batt_new.current = (int16_t)v; - - if (sb_read(SB_CHARGING_VOLTAGE, &batt_new.desired_voltage)) - batt_new.flags |= BATT_FLAG_BAD_DESIRED_VOLTAGE; - - if (sb_read(SB_CHARGING_CURRENT, &batt_new.desired_current)) - batt_new.flags |= BATT_FLAG_BAD_DESIRED_CURRENT; - - if (battery_remaining_capacity(&batt_new.remaining_capacity)) - batt_new.flags |= BATT_FLAG_BAD_REMAINING_CAPACITY; - - if (battery_full_charge_capacity(&batt_new.full_capacity)) - batt_new.flags |= BATT_FLAG_BAD_FULL_CAPACITY; - - if (battery_status(&batt_new.status)) - batt_new.flags |= BATT_FLAG_BAD_STATUS; - - /* If any of those reads worked, the battery is responsive */ - if ((batt_new.flags & BATT_FLAG_BAD_ANY) != BATT_FLAG_BAD_ANY) - batt_new.flags |= BATT_FLAG_RESPONSIVE; - -#ifdef CONFIG_BATTERY_MEASURE_IMBALANCE - if (battery_imbalance_mv() > CONFIG_BATTERY_MAX_IMBALANCE_MV) - batt_new.flags |= BATT_FLAG_IMBALANCED_CELL; -#endif - -#if defined(CONFIG_BATTERY_PRESENT_CUSTOM) || \ - defined(CONFIG_BATTERY_PRESENT_GPIO) - /* Hardware can tell us for certain */ - batt_new.is_present = battery_is_present(); -#else - /* No hardware test, so we only know it's there if it responds */ - if (batt_new.flags & BATT_FLAG_RESPONSIVE) - batt_new.is_present = BP_YES; - else - batt_new.is_present = BP_NOT_SURE; -#endif - - /* - * Charging allowed if both desired voltage and current are nonzero - * and battery isn't full (and we read them all correctly). - */ - if (!(batt_new.flags & (BATT_FLAG_BAD_DESIRED_VOLTAGE | - BATT_FLAG_BAD_DESIRED_CURRENT | - BATT_FLAG_BAD_STATE_OF_CHARGE)) && -#ifdef CONFIG_BATTERY_REQUESTS_NIL_WHEN_DEAD - /* - * TODO (crosbug.com/p/29467): remove this workaround - * for dead battery that requests no voltage/current - */ - ((batt_new.desired_voltage && - batt_new.desired_current && - batt_new.state_of_charge < BATTERY_LEVEL_FULL) || - (batt_new.desired_voltage == 0 && - batt_new.desired_current == 0 && -#ifdef CONFIG_BATTERY_DEAD_UNTIL_VALUE - batt_new.state_of_charge < CONFIG_BATTERY_DEAD_UNTIL_VALUE))) -#else - batt_new.state_of_charge == 0))) -#endif -#else - batt_new.desired_voltage && - batt_new.desired_current && - batt_new.state_of_charge < BATTERY_LEVEL_FULL) -#endif - batt_new.flags |= BATT_FLAG_WANT_CHARGE; - else - /* Force both to zero */ - batt_new.desired_voltage = batt_new.desired_current = 0; - -#ifdef HAS_TASK_HOSTCMD - /* if there is no host, we don't care about compensation */ - battery_compensate_params(&batt_new); -#endif - - /* Update visible battery parameters */ - memcpy(batt, &batt_new, sizeof(*batt)); -} - -/* Wait until battery is totally stable */ -int battery_wait_for_stable(void) -{ - int status; - uint64_t wait_timeout = get_time().val + BATTERY_NO_RESPONSE_TIMEOUT; - - CPRINTS("Wait for battery stabilized during %d", - BATTERY_NO_RESPONSE_TIMEOUT); - while (get_time().val < wait_timeout) { - /* Starting pinging battery */ - if (battery_status(&status) == EC_SUCCESS) { - /* Battery is stable */ - CPRINTS("battery responded with status %x", status); - return EC_SUCCESS; - } - msleep(25); /* clock stretching could hold 25ms */ - } - CPRINTS("battery not responding"); - return EC_ERROR_NOT_POWERED; -} - -#if defined(CONFIG_CMD_BATTFAKE) -static int command_battfake(int argc, char **argv) -{ - char *e; - int v; - - if (argc == 2) { - v = strtoi(argv[1], &e, 0); - if (*e || v < -1 || v > 100) - return EC_ERROR_PARAM1; - - fake_state_of_charge = v; - } - - if (fake_state_of_charge >= 0) - ccprintf("Fake batt %d%%\n", - fake_state_of_charge); - - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(battfake, command_battfake, - "percent (-1 = use real level)", - "Set fake battery level"); - -static int command_batttempfake(int argc, char **argv) -{ - char *e; - int t; - - if (argc == 2) { - t = strtoi(argv[1], &e, 0); - if (*e || t < -1 || t > 5000) - return EC_ERROR_PARAM1; - - fake_temperature = t; - } - - if (fake_temperature >= 0) - ccprintf("Fake batt temperature %d.%d K\n", - fake_temperature / 10, fake_temperature % 10); - - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(batttempfake, command_batttempfake, - "temperature (-1 = use real temperature)", - "Set fake battery temperature in deciKelvin (2731 = 273.1 K = 0 deg C)"); -#endif - -#ifdef CONFIG_CMD_BATT_MFG_ACCESS -static int command_batt_mfg_access_read(int argc, char **argv) -{ - char *e; - uint8_t data[32]; - int cmd, block, len = 6; - int rv; - - if (argc < 3 || argc > 4) - return EC_ERROR_PARAM_COUNT; - - cmd = strtoi(argv[1], &e, 0); - if (*e || cmd < 0) - return EC_ERROR_PARAM1; - - block = strtoi(argv[2], &e, 0); - if (*e || block < 0) - return EC_ERROR_PARAM2; - - if (argc > 3) { - len = strtoi(argv[3], &e, 0); - len += 2; - if (*e || len < 3 || len > sizeof(data)) - return EC_ERROR_PARAM3; - } - - rv = sb_read_mfgacc(cmd, block, data, len); - if (rv) - return rv; - - ccprintf("data[MSB->LSB]=0x"); - do { - len--; - ccprintf("%02x ", data[len]); - } while (len > 2); - ccprintf("\n"); - - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(battmfgacc, command_batt_mfg_access_read, - "cmd block | len", - "Read battery manufacture access data"); -#endif /* CONFIG_CMD_BATT_MFG_ACCESS */ - -/*****************************************************************************/ -/* Smart battery pass-through - */ -#ifdef CONFIG_I2C_PASSTHROUGH -static enum ec_status -host_command_sb_read_word(struct host_cmd_handler_args *args) -{ - int rv; - int val; - const struct ec_params_sb_rd *p = args->params; - struct ec_response_sb_rd_word *r = args->response; - - if (p->reg > 0x1c) - return EC_RES_INVALID_PARAM; - rv = sb_read(p->reg, &val); - if (rv) - return EC_RES_ERROR; - - r->value = val; - args->response_size = sizeof(struct ec_response_sb_rd_word); - - return EC_RES_SUCCESS; -} -DECLARE_HOST_COMMAND(EC_CMD_SB_READ_WORD, - host_command_sb_read_word, - EC_VER_MASK(0)); - -static enum ec_status -host_command_sb_write_word(struct host_cmd_handler_args *args) -{ - int rv; - const struct ec_params_sb_wr_word *p = args->params; - - if (p->reg > 0x1c) - return EC_RES_INVALID_PARAM; - rv = sb_write(p->reg, p->value); - if (rv) - return EC_RES_ERROR; - - return EC_RES_SUCCESS; -} -DECLARE_HOST_COMMAND(EC_CMD_SB_WRITE_WORD, - host_command_sb_write_word, - EC_VER_MASK(0)); - -static enum ec_status -host_command_sb_read_block(struct host_cmd_handler_args *args) -{ - int rv; - const struct ec_params_sb_rd *p = args->params; - struct ec_response_sb_rd_block *r = args->response; - - if ((p->reg != SB_MANUFACTURER_NAME) && - (p->reg != SB_DEVICE_NAME) && - (p->reg != SB_DEVICE_CHEMISTRY) && - (p->reg != SB_MANUFACTURER_DATA)) - return EC_RES_INVALID_PARAM; - rv = sb_read_string(p->reg, r->data, 32); - if (rv) - return EC_RES_ERROR; - - args->response_size = sizeof(struct ec_response_sb_rd_block); - - return EC_RES_SUCCESS; -} -DECLARE_HOST_COMMAND(EC_CMD_SB_READ_BLOCK, - host_command_sb_read_block, - EC_VER_MASK(0)); - -static enum ec_status -host_command_sb_write_block(struct host_cmd_handler_args *args) -{ - /* Not implemented */ - return EC_RES_INVALID_COMMAND; -} -DECLARE_HOST_COMMAND(EC_CMD_SB_WRITE_BLOCK, - host_command_sb_write_block, - EC_VER_MASK(0)); -#endif - -#ifdef CONFIG_CMD_I2C_STRESS_TEST_BATTERY -test_mockable int sb_i2c_test_read(int cmd, int *param) -{ - char chemistry[sizeof(CONFIG_BATTERY_DEVICE_CHEMISTRY) + 1]; - int rv; - - if (cmd == SB_DEVICE_CHEMISTRY) { - rv = battery_device_chemistry(chemistry, - sizeof(CONFIG_BATTERY_DEVICE_CHEMISTRY)); - if (rv) - return rv; - if (strcasecmp(chemistry, CONFIG_BATTERY_DEVICE_CHEMISTRY)) - return EC_ERROR_UNKNOWN; - - *param = EC_SUCCESS; - return EC_SUCCESS; - } - - - return sb_read(cmd, param); -} - -struct i2c_stress_test_dev battery_i2c_stress_test_dev = { - .reg_info = { - .read_reg = SB_DEVICE_CHEMISTRY, - .read_val = EC_SUCCESS, - .write_reg = SB_AT_RATE, - }, - .i2c_read_dev = &sb_i2c_test_read, - .i2c_write_dev = &sb_write, -}; -#endif /* CONFIG_CMD_I2C_STRESS_TEST_BATTERY */ diff --git a/driver/bc12/max14637.c b/driver/bc12/max14637.c deleted file mode 100644 index ca06b26aeb..0000000000 --- a/driver/bc12/max14637.c +++ /dev/null @@ -1,193 +0,0 @@ -/* Copyright 2017 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. - */ - -/* - * MAX14637 USB BC 1.2 Charger Detector driver. - * - * NOTE: The driver assumes that CHG_AL_N and SW_OPEN are not connected, - * therefore the value of CHG_DET indicates whether the source is NOT a - * low-power standard downstream port (SDP). In order to use higher currents, - * the system will have to charge ramp. - */ - -#include "max14637.h" -#include "cannonlake.h" -#include "charge_manager.h" -#include "chipset.h" -#include "common.h" -#include "console.h" -#include "gpio.h" -#include "power.h" -#include "task.h" -#include "tcpm.h" -#include "timer.h" -#include "usb_charge.h" -#include "usb_pd.h" -#include "util.h" - -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) - -#if defined(CONFIG_CHARGE_RAMP_SW) || defined(CONFIG_CHARGE_RAMP_HW) -/** - * Returns true if the charger detect pin is activated. - * - * @parm cfg driver for chip to read the charger detect pin for. - * @return 1 if charger detect is activated (high when active high or - * low with active low), otherwise 0. - */ -static int is_chg_det_activated(const struct max14637_config_t * const cfg) -{ - return !!gpio_get_level(cfg->chg_det_pin) ^ - !!(cfg->flags & MAX14637_FLAGS_CHG_DET_ACTIVE_LOW); -} -#endif - -/** - * Activates the Chip Enable GPIO based on the enabled value. - * - * @param cfg driver for chip that will set chip enable gpio. - * @param enable 1 to activate gpio (high for active high and low for active - * low). - */ -static void activate_chip_enable( - const struct max14637_config_t * const cfg, const int enable) -{ - gpio_set_level( - cfg->chip_enable_pin, - !!enable ^ !!(cfg->flags & MAX14637_FLAGS_ENABLE_ACTIVE_LOW)); -} - -/** - * Perform BC1.2 detection and update charge manager. - * - * @param port: The Type-C port where VBUS is present. - */ -static void bc12_detect(const int port) -{ - const struct max14637_config_t * const cfg = &max14637_config[port]; - struct charge_port_info new_chg; - - /* - * Enable the IC to begin detection and connect switches if necessary. - */ - activate_chip_enable(cfg, 1); - - new_chg.voltage = USB_CHARGER_VOLTAGE_MV; -#if defined(CONFIG_CHARGE_RAMP_SW) || defined(CONFIG_CHARGE_RAMP_HW) - /* - * Apple or TomTom charger detection can take as long as 600ms. Wait a - * little bit longer for margin. - */ - msleep(630); - - /* - * The driver assumes that CHG_AL_N and SW_OPEN are not connected, - * therefore an activated CHG_DET indicates whether the source is NOT a - * low-power standard downstream port (SDP). The system will have to - * ramp the current to determine the limit. - */ - new_chg.current = is_chg_det_activated(cfg) ? 2400 : 500; -#else - /* - * If the board doesn't support charge ramping, then assume the lowest - * denominator; that is assume the charger detected is a weak dedicated - * charging port (DCP) which can only supply 500mA. - */ - new_chg.current = 500; -#endif /* !defined(CONFIG_CHARGE_RAMP_SW && CONFIG_CHARGE_RAMP_HW) */ - - charge_manager_update_charge(CHARGE_SUPPLIER_OTHER, port, &new_chg); -} - -/** - * Turn off the MAX14637 detector. - * - * @param port: Which USB Type-C port's BC1.2 detector to turn off. - */ -static void power_down_ic(const int port) -{ - const struct max14637_config_t * const cfg = &max14637_config[port]; - - /* Turn off the IC. */ - activate_chip_enable(cfg, 0); - - /* Let charge manager know there's no more charge available. */ - charge_manager_update_charge(CHARGE_SUPPLIER_OTHER, port, NULL); -} - -/** - * If VBUS is present, determine the charger type, otherwise power down the IC. - * - * @param port: Which USB Type-C port to examine. - */ -static void detect_or_power_down_ic(const int port) -{ - int vbus_present; - -#ifdef CONFIG_USB_PD_VBUS_DETECT_TCPC - vbus_present = tcpm_get_vbus_level(port); -#else - vbus_present = pd_snk_is_vbus_provided(port); -#endif /* !defined(CONFIG_USB_PD_VBUS_DETECT_TCPC) */ - - if (vbus_present) { -#if defined(CONFIG_POWER_PP5000_CONTROL) && defined(HAS_TASK_CHIPSET) - /* Turn on the 5V rail to allow the chip to be powered. */ - power_5v_enable(task_get_current(), 1); -#endif - bc12_detect(port); - } else { - power_down_ic(port); -#if defined(CONFIG_POWER_PP5000_CONTROL) && defined(HAS_TASK_CHIPSET) - /* Issue a request to turn off the rail. */ - power_5v_enable(task_get_current(), 0); -#endif - } -} - -void usb_charger_task(void *u) -{ - const int port = (intptr_t)u; - uint32_t evt; - - ASSERT(port >= 0 && port < CONFIG_USB_PD_PORT_MAX_COUNT); - - detect_or_power_down_ic(port); - - while (1) { - evt = task_wait_event(-1); - - if (evt & USB_CHG_EVENT_VBUS) - detect_or_power_down_ic(port); - } -} - -void usb_charger_set_switches(int port, enum usb_switch setting) -{ - /* - * The MAX14637 automatically sets up the USB 2.0 high-speed switches. - */ -} - -#if defined(CONFIG_CHARGE_RAMP_SW) || defined(CONFIG_CHARGE_RAMP_HW) -int usb_charger_ramp_allowed(int supplier) -{ - /* - * Due to the limitations in the application of the MAX14637, we - * don't quite know exactly what we're plugged into. Therefore, - * the supplier type will be CHARGE_SUPPLIER_OTHER. - */ - return supplier == CHARGE_SUPPLIER_OTHER; -} - -int usb_charger_ramp_max(int supplier, int sup_curr) -{ - /* Use the current limit that was decided by the MAX14637. */ - if (supplier == CHARGE_SUPPLIER_OTHER) - return sup_curr; - else - return 500; -} -#endif /* CONFIG_CHARGE_RAMP_SW || CONFIG_CHARGE_RAMP_HW */ diff --git a/driver/bc12/max14637.h b/driver/bc12/max14637.h deleted file mode 100644 index 789504b1eb..0000000000 --- a/driver/bc12/max14637.h +++ /dev/null @@ -1,32 +0,0 @@ -/* Copyright 2018 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. - */ - -/* MAX14637 USB BC 1.2 Charger Detector driver definitions */ - -#include "gpio.h" - -#define MAX14637_FLAGS_ENABLE_ACTIVE_LOW BIT(0) -#define MAX14637_FLAGS_CHG_DET_ACTIVE_LOW BIT(1) - -struct max14637_config_t { - /* - * Enable signal to BC 1.2. Can be active high or low depending on - * MAX14637_FLAGS_ENABLE_ACTIVE_LOW flag bit. - */ - enum gpio_signal chip_enable_pin; - /* - * Charger detect signal from BC 1.2 chip. Can be active high or low - * depending on MAX14637_FLAGS_CHG_DET_ACTIVE_LOW flag bit. - */ - enum gpio_signal chg_det_pin; - /* Configuration flags with prefix MAX14637_FLAGS. */ - int flags; -}; - -/* - * Array that contains boards-specific configuration for BC 1.2 charging chips. - */ -extern const struct max14637_config_t - max14637_config[CONFIG_USB_PD_PORT_MAX_COUNT]; diff --git a/driver/bc12/pi3usb9201.c b/driver/bc12/pi3usb9201.c deleted file mode 100644 index 7f11e1da8a..0000000000 --- a/driver/bc12/pi3usb9201.c +++ /dev/null @@ -1,371 +0,0 @@ -/* Copyright 2019 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. - */ - -/* PI3USB9201 USB BC 1.2 Charger Detector driver. */ - -#include "pi3usb9201.h" -#include "charge_manager.h" -#include "chipset.h" -#include "common.h" -#include "console.h" -#include "gpio.h" -#include "power.h" -#include "task.h" -#include "tcpm.h" -#include "timer.h" -#include "usb_charge.h" -#include "usb_pd.h" -#include "util.h" - -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) - -enum pi3usb9201_client_sts { - CHG_OTHER = 0, - CHG_2_4A, - CHG_2_0A, - CHG_1_0A, - CHG_RESERVED, - CHG_CDP, - CHG_SDP, - CHG_DCP, -}; - -struct bc12_status { - enum charge_supplier supplier; - int current_limit; -}; - -/* Used to store last BC1.2 detection result */ -static enum charge_supplier bc12_supplier[CONFIG_USB_PD_PORT_MAX_COUNT]; - -static const struct bc12_status bc12_chg_limits[] = { - [CHG_OTHER] = {CHARGE_SUPPLIER_OTHER, 500}, - [CHG_2_4A] = {CHARGE_SUPPLIER_PROPRIETARY, 2400}, - [CHG_2_0A] = {CHARGE_SUPPLIER_PROPRIETARY, 2000}, - [CHG_1_0A] = {CHARGE_SUPPLIER_PROPRIETARY, 1000}, - [CHG_RESERVED] = {CHARGE_SUPPLIER_NONE, 0}, - [CHG_CDP] = {CHARGE_SUPPLIER_BC12_CDP, 1500}, - [CHG_SDP] = {CHARGE_SUPPLIER_BC12_SDP, 500}, -#if defined(CONFIG_CHARGE_RAMP_SW) || defined(CONFIG_CHARGE_RAMP_HW) - /* - * If ramping is supported, then for DCP set the current limit to be the - * max supported for the port by the board. This because for DCP the - * charger is allowed to set its own max up to 5A. - */ - [CHG_DCP] = {CHARGE_SUPPLIER_BC12_DCP, PD_MAX_CURRENT_MA}, -#else - [CHG_DCP] = {CHARGE_SUPPLIER_BC12_DCP, 500}, -#endif -}; - -static inline int raw_read8(int port, int offset, int *value) -{ - return i2c_read8(pi3usb9201_bc12_chips[port].i2c_port, - pi3usb9201_bc12_chips[port].i2c_addr_flags, - offset, value); -} - -static inline int raw_write8(int port, int offset, int value) -{ - return i2c_write8(pi3usb9201_bc12_chips[port].i2c_port, - pi3usb9201_bc12_chips[port].i2c_addr_flags, - offset, value); -} - -static int pi3usb9201_raw(int port, int reg, int mask, int val) -{ - int rv; - int reg_val; - - rv = raw_read8(port, reg, ®_val); - if (rv) - return rv; - - reg_val &= ~mask; - reg_val |= val; - - return raw_write8(port, reg, reg_val); -} - -static int pi3usb9201_interrupt_mask(int port, int enable) -{ - return pi3usb9201_raw(port, PI3USB9201_REG_CTRL_1, - PI3USB9201_REG_CTRL_1_INT_MASK, - enable); -} - -static int pi3usb9201_bc12_detect_ctrl(int port, int enable) -{ - return pi3usb9201_raw(port, PI3USB9201_REG_CTRL_2, - PI3USB9201_REG_CTRL_2_START_DET, - enable ? PI3USB9201_REG_CTRL_2_START_DET : 0); -} - -static int pi3usb9201_set_mode(int port, int desired_mode) -{ - return pi3usb9201_raw(port, PI3USB9201_REG_CTRL_1, - PI3USB9201_REG_CTRL_1_MODE_MASK, - desired_mode << PI3USB9201_REG_CTRL_1_MODE_SHIFT); -} - -static int pi3usb9201_get_mode(int port, int *mode) -{ - int rv; - - rv = raw_read8(port, PI3USB9201_REG_CTRL_1, mode); - if (rv) - return rv; - - *mode &= PI3USB9201_REG_CTRL_1_MODE_MASK; - *mode >>= PI3USB9201_REG_CTRL_1_MODE_SHIFT; - - return EC_SUCCESS; -} - -static int pi3usb9201_get_status(int port, int *client, int *host) -{ - int rv; - int status; - - rv = raw_read8(port, PI3USB9201_REG_CLIENT_STS, &status); - if (client) - *client = status; - rv |= raw_read8(port, PI3USB9201_REG_HOST_STS, &status); - if (host) - *host = status; - - return rv; -} - -static void bc12_update_supplier(enum charge_supplier supplier, int port, - struct charge_port_info *new_chg) -{ - /* - * If most recent supplier type is not CHARGE_SUPPLIER_NONE, then the - * charge manager table entry for that supplier type needs to be cleared - * out. - */ - if (bc12_supplier[port] != CHARGE_SUPPLIER_NONE) - charge_manager_update_charge(bc12_supplier[port], port, NULL); - /* Now update the current supplier type */ - bc12_supplier[port] = supplier; - /* If new supplier type != NONE, then notify charge manager */ - if (supplier != CHARGE_SUPPLIER_NONE) - charge_manager_update_charge(supplier, port, new_chg); -} - -static void bc12_update_charge_manager(int port, int client_status) -{ - struct charge_port_info new_chg; - enum charge_supplier supplier; - int bit_pos; - - /* Set charge voltage to 5V */ - new_chg.voltage = USB_CHARGER_VOLTAGE_MV; - - /* - * Find set bit position. Note that this funciton is only called if a - * bit was set in client_status, so bit_pos won't be negative. - */ - bit_pos = __builtin_ffs(client_status) - 1; - - new_chg.current = bc12_chg_limits[bit_pos].current_limit; - supplier = bc12_chg_limits[bit_pos].supplier; - - CPRINTS("pi3usb9201[p%d]: sts = 0x%x, lim = %d mA, supplier = %d", - port, client_status, new_chg.current, supplier); - /* bc1.2 is complete and start bit does not auto clear */ - pi3usb9201_bc12_detect_ctrl(port, 0); - /* Inform charge manager of new supplier type and current limit */ - bc12_update_supplier(supplier, port, &new_chg); -} - -static int bc12_detect_start(int port) -{ - int rv; - - /* - * Read both status registers to ensure that all interrupt indications - * are cleared prior to starting bc1.2 detection. - */ - pi3usb9201_get_status(port, NULL, NULL); - - /* Put pi3usb9201 into client mode */ - rv = pi3usb9201_set_mode(port, PI3USB9201_CLIENT_MODE); - if (rv) - return rv; - /* Have pi3usb9201 start bc1.2 detection */ - rv = pi3usb9201_bc12_detect_ctrl(port, 1); - if (rv) - return rv; - /* Unmask interrupt to wake task when detection completes */ - return pi3usb9201_interrupt_mask(port, 0); -} - -static void bc12_power_down(int port) -{ - /* Put pi3usb9201 into its power down mode */ - pi3usb9201_set_mode(port, PI3USB9201_POWER_DOWN); - /* The start bc1.2 bit does not auto clear */ - pi3usb9201_bc12_detect_ctrl(port, 0); - /* Mask interrupts unitl next bc1.2 detection event */ - pi3usb9201_interrupt_mask(port, 1); - /* - * Let charge manager know there's no more charge available for the - * supplier type that was most recently detected. - */ - bc12_update_supplier(CHARGE_SUPPLIER_NONE, port, NULL); -#if defined(CONFIG_POWER_PP5000_CONTROL) && defined(HAS_TASK_CHIPSET) - /* Indicate PP5000_A rail is not required by USB_CHG task. */ - power_5v_enable(task_get_current(), 0); -#endif -} - -static void bc12_power_up(int port) -{ -#if defined(CONFIG_POWER_PP5000_CONTROL) && defined(HAS_TASK_CHIPSET) - /* Turn on the 5V rail to allow the chip to be powered. */ - power_5v_enable(task_get_current(), 1); - /* Give the pi3usb9201 time so it's ready to receive i2c messages */ - msleep(1); -#endif - pi3usb9201_interrupt_mask(port, 1); -} - -void usb_charger_task(void *u) -{ - int port = (task_get_current() == TASK_ID_USB_CHG_P0 ? 0 : 1); - uint32_t evt; - int i; - - /* - * Set most recent bc1.2 detection supplier result to - * CHARGE_SUPPLIER_NONE for all ports. - */ - for (i = 0; i < board_get_usb_pd_port_count(); i++) - bc12_supplier[port] = CHARGE_SUPPLIER_NONE; - - /* - * The is no specific initialization required for the pi3usb9201 other - * than enabling the interrupt mask. - */ - pi3usb9201_interrupt_mask(port, 1); - - while (1) { - /* Wait for interrupt */ - evt = task_wait_event(-1); - - /* Interrupt from the Pericom chip, determine charger type */ - if (evt & USB_CHG_EVENT_BC12) { - int client; - int rv; - - rv = pi3usb9201_get_status(port, &client, NULL); - if (!rv && client) - /* - * Any bit set in client status register - * indicates that BC1.2 detection has - * completed. - */ - bc12_update_charge_manager(port, client); - } - -#ifndef CONFIG_USB_PD_VBUS_DETECT_TCPC - if (evt & USB_CHG_EVENT_VBUS) - CPRINTS("VBUS p%d %d", port, - pd_snk_is_vbus_provided(port)); -#endif - - if (evt & USB_CHG_EVENT_DR_UFP) { - bc12_power_up(port); - if (bc12_detect_start(port)) { - struct charge_port_info new_chg; - - /* - * VBUS is present, but starting bc1.2 detection - * failed for some reason. So limit charge - * current to default 500 mA for this case. - */ - - new_chg.voltage = USB_CHARGER_VOLTAGE_MV; - new_chg.current = USB_CHARGER_MIN_CURR_MA; - /* Save supplier type and notify chg manager */ - bc12_update_supplier(CHARGE_SUPPLIER_OTHER, - port, &new_chg); - CPRINTS("pi3usb9201[p%d]: bc1.2 failed use " - "defaults", port); - } - } - - /* - * TODO(b/124061702): For host mode, currently only setting it - * to host CDP mode. However, there are 3 host status bits to - * know things such as an adapter connected, but no USB device - * present, or bc1.2 activity detected. - */ - if (evt & USB_CHG_EVENT_DR_DFP) { - int mode; - int rv; - - /* - * Update the charge manager if bc1.2 client mode is - * currently active. - */ - bc12_update_supplier(CHARGE_SUPPLIER_NONE, port, NULL); - /* - * If the port is in DFP mode, then need to set mode to - * CDP_HOST which will auto close D+/D- switches. - */ - bc12_power_up(port); - rv = pi3usb9201_get_mode(port, &mode); - if (!rv && (mode != PI3USB9201_CDP_HOST_MODE)) { - CPRINTS("pi3usb9201[p%d]: CDP_HOST mode", port); - pi3usb9201_set_mode(port, - PI3USB9201_CDP_HOST_MODE); - } - } - - if (evt & USB_CHG_EVENT_CC_OPEN) - bc12_power_down(port); - } -} - -void usb_charger_set_switches(int port, enum usb_switch setting) -{ - /* - * Switches are controlled automatically based on whether the port is - * acting as a source or as sink and the result of BC1.2 detection. - */ -} - -#if defined(CONFIG_CHARGE_RAMP_SW) || defined(CONFIG_CHARGE_RAMP_HW) -int usb_charger_ramp_allowed(int supplier) -{ - /* Don't allow ramp if charge supplier is OTHER, SDP, or NONE */ - return !(supplier == CHARGE_SUPPLIER_OTHER || - supplier == CHARGE_SUPPLIER_BC12_SDP || - supplier == CHARGE_SUPPLIER_NONE); -} - -int usb_charger_ramp_max(int supplier, int sup_curr) -{ - /* - * Use the level from the bc12_chg_limits table above except for - * proprietary of CDP and in those cases the charge current from the - * charge manager is already set at the max determined by bc1.2 - * detection. - */ - switch (supplier) { - case CHARGE_SUPPLIER_BC12_DCP: - return PD_MAX_CURRENT_MA; - case CHARGE_SUPPLIER_BC12_CDP: - case CHARGE_SUPPLIER_PROPRIETARY: - return sup_curr; - case CHARGE_SUPPLIER_BC12_SDP: - default: - return 500; - } -} -#endif /* CONFIG_CHARGE_RAMP_SW || CONFIG_CHARGE_RAMP_HW */ diff --git a/driver/bc12/pi3usb9201.h b/driver/bc12/pi3usb9201.h deleted file mode 100644 index d9ee80a0d0..0000000000 --- a/driver/bc12/pi3usb9201.h +++ /dev/null @@ -1,52 +0,0 @@ -/* Copyright 2019 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. - */ - -/* PI3USB9201 USB BC 1.2 Charger Detector driver definitions */ - -/* I2C address */ -#define PI3USB9201_I2C_ADDR_0_FLAGS 0x5C -#define PI3USB9201_I2C_ADDR_1_FLAGS 0x5D -#define PI3USB9201_I2C_ADDR_2_FLAGS 0x5E -#define PI3USB9201_I2C_ADDR_3_FLAGS 0x5F - -#define PI3USB9201_REG_CTRL_1 0x0 -#define PI3USB9201_REG_CTRL_2 0x1 -#define PI3USB9201_REG_CLIENT_STS 0x2 -#define PI3USB9201_REG_HOST_STS 0x3 - -/* Control_1 regiter bit definitions */ -#define PI3USB9201_REG_CTRL_1_INT_MASK BIT(0) -#define PI3USB9201_REG_CTRL_1_MODE_SHIFT 1 -#define PI3USB9201_REG_CTRL_1_MODE_MASK (0x7 << \ - PI3USB9201_REG_CTRL_1_MODE_SHIFT) - -/* Control_2 regiter bit definitions */ -#define PI3USB9201_REG_CTRL_2_AUTO_SW BIT(1) -#define PI3USB9201_REG_CTRL_2_START_DET BIT(3) - -/* Host status register bit definitions */ -#define PI3USB9201_REG_HOST_STS_BC12_DET BIT(0) -#define PI3USB9201_REG_HOST_STS_DEV_PLUG BIT(1) -#define PI3USB9201_REG_HOST_STS_DEV_UNPLUG BIT(2) - -struct pi3usb9201_config_t { - const int i2c_port; - const int i2c_addr_flags; -}; - -enum pi3usb9201_mode { - PI3USB9201_POWER_DOWN, - PI3USB9201_SDP_HOST_MODE, - PI3USB9201_DCP_HOST_MODE, - PI3USB9201_CDP_HOST_MODE, - PI3USB9201_CLIENT_MODE, - PI3USB9201_RESERVED_1, - PI3USB9201_RESERVED_2, - PI3USB9201_USB_PATH_ON, -}; - -/* Configuration struct defined at board level */ -extern const struct pi3usb9201_config_t pi3usb9201_bc12_chips[]; - diff --git a/driver/bc12/pi3usb9281.c b/driver/bc12/pi3usb9281.c deleted file mode 100644 index db5d039fd9..0000000000 --- a/driver/bc12/pi3usb9281.c +++ /dev/null @@ -1,482 +0,0 @@ -/* Copyright 2014 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. - * - * Pericom PI3USB3281 USB port switch driver. - */ - -#include "charge_manager.h" -#include "common.h" -#include "console.h" -#include "ec_commands.h" -#include "gpio.h" -#include "hooks.h" -#include "i2c.h" -#include "pi3usb9281.h" -#include "task.h" -#include "timer.h" -#include "usb_charge.h" -#include "usb_pd.h" -#include "util.h" - - /* Console output macros */ -#define CPUTS(outstr) cputs(CC_USBCHARGE, outstr) -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) - -/* I2C address */ -#define PI3USB9281_I2C_ADDR_FLAGS 0x25 - -/* Delay values */ -#define PI3USB9281_SW_RESET_DELAY 20 - -/* Wait after a charger is detected to debounce pin contact order */ -#define PI3USB9281_DETECT_DEBOUNCE_MS 1000 -#define PI3USB9281_RESET_DEBOUNCE_MS 100 -#define PI3USB9281_RESET_STARTUP_DELAY (200 * MSEC) -#define PI3USB9281_RESET_STARTUP_DELAY_INTERVAL_MS 40 - -/* Store the state of our USB data switches so that they can be restored. */ -static int usb_switch_state[CONFIG_USB_PD_PORT_MAX_COUNT]; - -static int pi3usb9281_reset(int port); -static int pi3usb9281_get_interrupts(int port); - -static void select_chip(int port) -{ - struct pi3usb9281_config *chip = &pi3usb9281_chips[port]; - ASSERT(port < CONFIG_BC12_DETECT_PI3USB9281_CHIP_COUNT); - - if (chip->mux_lock) { - mutex_lock(chip->mux_lock); - gpio_set_level(chip->mux_gpio, chip->mux_gpio_level); - } -} - -static void unselect_chip(int port) -{ - struct pi3usb9281_config *chip = &pi3usb9281_chips[port]; - - if (chip->mux_lock) - /* Just release the mutex, no need to change the mux gpio */ - mutex_unlock(chip->mux_lock); -} - -static uint8_t pi3usb9281_do_read(int port, uint8_t reg, int with_lock) -{ - struct pi3usb9281_config *chip = &pi3usb9281_chips[port]; - int res, val; - - if (with_lock) - select_chip(port); - - res = i2c_read8(chip->i2c_port, PI3USB9281_I2C_ADDR_FLAGS, - reg, &val); - - if (with_lock) - unselect_chip(port); - - if (res) - return 0xee; - - return val; -} - -static uint8_t pi3usb9281_read_u(int port, uint8_t reg) -{ - return pi3usb9281_do_read(port, reg, 0); -} - -static uint8_t pi3usb9281_read(int port, uint8_t reg) -{ - return pi3usb9281_do_read(port, reg, 1); -} - -static int pi3usb9281_do_write( - int port, uint8_t reg, uint8_t val, int with_lock) -{ - struct pi3usb9281_config *chip = &pi3usb9281_chips[port]; - int res; - - if (with_lock) - select_chip(port); - - res = i2c_write8(chip->i2c_port, PI3USB9281_I2C_ADDR_FLAGS, - reg, val); - - if (with_lock) - unselect_chip(port); - - if (res) - CPRINTS("PI3USB9281 I2C write failed"); - return res; -} - -static int pi3usb9281_write(int port, uint8_t reg, uint8_t val) -{ - return pi3usb9281_do_write(port, reg, val, 1); -} - -/* Write control register, taking care to correctly set reserved bits. */ -static int pi3usb9281_do_write_ctrl(int port, uint8_t ctrl, int with_lock) -{ - return pi3usb9281_do_write(port, PI3USB9281_REG_CONTROL, - (ctrl & PI3USB9281_CTRL_MASK) | - PI3USB9281_CTRL_RSVD_1, with_lock); -} - -static int pi3usb9281_write_ctrl(int port, uint8_t ctrl) -{ - return pi3usb9281_do_write_ctrl(port, ctrl, 1); -} - -static int pi3usb9281_write_ctrl_u(int port, uint8_t ctrl) -{ - return pi3usb9281_do_write_ctrl(port, ctrl, 0); -} - -/* - * Mask particular interrupts (e.g. attach, detach, ovp, ocp). - * 1: UnMask (enable). 0: Mask (disable) - */ -static int pi3usb9281_set_interrupt_mask(int port, uint8_t mask) -{ - return pi3usb9281_write(port, PI3USB9281_REG_INT_MASK, ~mask); -} - -static void pi3usb9281_init(int port) -{ - uint8_t dev_id; - - dev_id = pi3usb9281_read(port, PI3USB9281_REG_DEV_ID); - - if (dev_id != PI3USB9281_DEV_ID && dev_id != PI3USB9281_DEV_ID_A) - CPRINTS("PI3USB9281 invalid ID 0x%02x", dev_id); - - pi3usb9281_reset(port); - pi3usb9281_enable_interrupts(port); -} - - -int pi3usb9281_enable_interrupts(int port) -{ - uint8_t ctrl; - pi3usb9281_set_interrupt_mask(port, PI3USB9281_INT_ATTACH_DETACH); - ctrl = pi3usb9281_read(port, PI3USB9281_REG_CONTROL); - if (ctrl == 0xee) - return EC_ERROR_UNKNOWN; - - return pi3usb9281_write_ctrl(port, ctrl & ~PI3USB9281_CTRL_INT_DIS); -} - -static int pi3usb9281_disable_interrupts(int port) -{ - uint8_t ctrl = pi3usb9281_read(port, PI3USB9281_REG_CONTROL); - int rv; - - if (ctrl == 0xee) - return EC_ERROR_UNKNOWN; - - rv = pi3usb9281_write_ctrl(port, ctrl | PI3USB9281_CTRL_INT_DIS); - pi3usb9281_get_interrupts(port); - return rv; -} - -static int pi3usb9281_get_interrupts(int port) -{ - return pi3usb9281_read(port, PI3USB9281_REG_INT); -} - -int pi3usb9281_get_device_type(int port) -{ - return pi3usb9281_read(port, PI3USB9281_REG_DEV_TYPE) & 0x77; -} - -static int pi3usb9281_get_charger_status(int port) -{ - return pi3usb9281_read(port, PI3USB9281_REG_CHG_STATUS) & 0x1f; -} - -static int pi3usb9281_get_ilim(int device_type, int charger_status) -{ - /* Limit USB port current. 500mA for not listed types. */ - int current_limit_ma = 500; - - if (charger_status & PI3USB9281_CHG_CAR_TYPE1 || - charger_status & PI3USB9281_CHG_CAR_TYPE2) - current_limit_ma = 3000; - else if (charger_status & PI3USB9281_CHG_APPLE_1A) - current_limit_ma = 1000; - else if (charger_status & PI3USB9281_CHG_APPLE_2A) - current_limit_ma = 2000; - else if (charger_status & PI3USB9281_CHG_APPLE_2_4A) - current_limit_ma = 2400; - else if (device_type & PI3USB9281_TYPE_CDP) - current_limit_ma = 1500; - else if (device_type & PI3USB9281_TYPE_DCP) - current_limit_ma = 500; - - return current_limit_ma; -} - -static int pi3usb9281_reset(int port) -{ - int rv = pi3usb9281_write(port, PI3USB9281_REG_RESET, 0x1); - - if (!rv) - /* Reset takes ~15ms. Wait for 20ms to be safe. */ - msleep(PI3USB9281_SW_RESET_DELAY); - - return rv; -} - -static int pi3usb9281_set_switch_manual(int port, int val) -{ - int res = EC_ERROR_UNKNOWN; - uint8_t ctrl; - - select_chip(port); - ctrl = pi3usb9281_read_u(port, PI3USB9281_REG_CONTROL); - - if (ctrl != 0xee) { - if (val) - ctrl &= ~PI3USB9281_CTRL_AUTO; - else - ctrl |= PI3USB9281_CTRL_AUTO; - res = pi3usb9281_write_ctrl_u(port, ctrl); - } - - unselect_chip(port); - return res; -} - -static int pi3usb9281_set_pins(int port, uint8_t val) -{ - return pi3usb9281_write(port, PI3USB9281_REG_MANUAL, val); -} - -static int pi3usb9281_set_switches(int port, int open) -{ - int res = EC_ERROR_UNKNOWN; - uint8_t ctrl; - - select_chip(port); - ctrl = pi3usb9281_read_u(port, PI3USB9281_REG_CONTROL); - - if (ctrl != 0xee) { - if (open) - ctrl &= ~PI3USB9281_CTRL_SWITCH_AUTO; - else - ctrl |= PI3USB9281_CTRL_SWITCH_AUTO; - res = pi3usb9281_write_ctrl_u(port, ctrl); - } - - unselect_chip(port); - return res; -} - -void usb_charger_set_switches(int port, enum usb_switch setting) -{ - /* If switch is not changing then return */ - if (setting == usb_switch_state[port]) - return; - if (setting != USB_SWITCH_RESTORE) - usb_switch_state[port] = setting; - CPRINTS("USB MUX %d", usb_switch_state[port]); - task_set_event(TASK_ID_USB_CHG_P0 + port, USB_CHG_EVENT_MUX, 0); -} - -static int pc3usb9281_read_interrupt(int port) -{ - timestamp_t timeout; - timeout.val = get_time().val + PI3USB9281_RESET_STARTUP_DELAY; - do { - /* Read (& clear) possible attach & detach interrupt */ - if (pi3usb9281_get_interrupts(port) & - PI3USB9281_INT_ATTACH_DETACH) - return EC_SUCCESS; - msleep(PI3USB9281_RESET_STARTUP_DELAY_INTERVAL_MS); - } while (get_time().val < timeout.val); - return EC_ERROR_TIMEOUT; -} - -/* - * Handle BC 1.2 attach & detach event - * - * On attach, it resets pi3usb9281 for debounce. This reset should immediately - * trigger another attach or detach interrupt. If other (unexpected) event is - * observed, it forwards the event so that the caller can handle it. - */ -static uint32_t bc12_detect(int port) -{ - int device_type, chg_status; - uint32_t evt = 0; - - if (usb_charger_port_is_sourcing_vbus(port)) { - /* If we're sourcing VBUS then we're not charging */ - device_type = PI3USB9281_TYPE_NONE; - chg_status = PI3USB9281_CHG_NONE; - } else { - /* Set device type */ - device_type = pi3usb9281_get_device_type(port); - chg_status = pi3usb9281_get_charger_status(port); - } - - /* Debounce pin plug order if we detect a charger */ - if (device_type || PI3USB9281_CHG_STATUS_ANY(chg_status)) { - /* next operation might trigger a detach interrupt */ - pi3usb9281_disable_interrupts(port); - /* - * Ensure D+/D- are open before resetting - * Note: we can't simply call pi3usb9281_set_switches() because - * another task might override it and set the switches closed. - */ - pi3usb9281_set_switch_manual(port, 1); - pi3usb9281_set_pins(port, 0); - - /* Delay to debounce pin attach order */ - msleep(PI3USB9281_DETECT_DEBOUNCE_MS); - - /* - * Reset PI3USB9281 to refresh detection registers. After reset, - * - Interrupt is globally disabled - * - All interrupts are unmasked (=enabled) - * - * WARNING: This reset is acceptable for samus_pd, - * but may not be acceptable for devices that have - * an OTG / device mode, as we may be interrupting - * the connection. - */ - pi3usb9281_reset(port); - - /* - * Restore data switch settings - switches return to - * closed on reset until restored. - */ - usb_charger_set_switches(port, USB_SWITCH_RESTORE); - - /* - * Wait after reset, before re-enabling interrupt, so that - * spurious interrupts from this port are ignored. - */ - msleep(PI3USB9281_RESET_DEBOUNCE_MS); - - /* Re-enable interrupts */ - pi3usb9281_enable_interrupts(port); - - /* - * Consume interrupt (expectedly) triggered by the reset. - * If it's other event (e.g. VBUS), return immediately. - */ - evt = task_wait_event(PI3USB9281_RESET_DEBOUNCE_MS * MSEC); - if (evt & USB_CHG_EVENT_BC12) - evt &= ~USB_CHG_EVENT_BC12; - else if (evt & USB_CHG_EVENT_INTR) - evt &= ~USB_CHG_EVENT_INTR; - else - return evt; - - /* Debounce is done. Registers should have trustworthy values */ - device_type = PI3USB9281_TYPE_NONE; - chg_status = PI3USB9281_CHG_NONE; - if (pc3usb9281_read_interrupt(port) == EC_SUCCESS) { - device_type = pi3usb9281_get_device_type(port); - chg_status = pi3usb9281_get_charger_status(port); - } - } - - /* Attachment: decode + update available charge */ - if (device_type || PI3USB9281_CHG_STATUS_ANY(chg_status)) { - struct charge_port_info chg; - int type; - - if (PI3USB9281_CHG_STATUS_ANY(chg_status)) - type = CHARGE_SUPPLIER_PROPRIETARY; - else if (device_type & PI3USB9281_TYPE_CDP) - type = CHARGE_SUPPLIER_BC12_CDP; - else if (device_type & PI3USB9281_TYPE_DCP) - type = CHARGE_SUPPLIER_BC12_DCP; - else if (device_type & PI3USB9281_TYPE_SDP) - type = CHARGE_SUPPLIER_BC12_SDP; - else - type = CHARGE_SUPPLIER_OTHER; - - chg.voltage = USB_CHARGER_VOLTAGE_MV; - chg.current = pi3usb9281_get_ilim(device_type, chg_status); - charge_manager_update_charge(type, port, &chg); - } else { - /* Detachment: update available charge to 0 */ - usb_charger_reset_charge(port); - } - - return evt; -} - -void usb_charger_task(void *u) -{ - int port = (task_get_current() == TASK_ID_USB_CHG_P0 ? 0 : 1); - uint32_t evt; - - /* Initialize chip and enable interrupts */ - pi3usb9281_init(port); - - evt = bc12_detect(port); - - while (1) { - /* Interrupt from the Pericom chip, determine charger type */ - if (evt & USB_CHG_EVENT_BC12) { - /* Read interrupt register to clear on chip */ - pi3usb9281_get_interrupts(port); - evt = bc12_detect(port); - } else if (evt & USB_CHG_EVENT_INTR) { - /* USB_CHG_EVENT_INTR & _BC12 are mutually exclusive */ - /* Check the interrupt register, and clear on chip */ - if (pi3usb9281_get_interrupts(port) & - PI3USB9281_INT_ATTACH_DETACH) - evt = bc12_detect(port); - } - - if (evt & USB_CHG_EVENT_MUX) - pi3usb9281_set_switches(port, usb_switch_state[port]); - - /* - * Re-enable interrupts on pericom charger detector since the - * chip may periodically reset itself, and come back up with - * registers in default state. TODO(crosbug.com/p/33823): Fix - * these unwanted resets. - */ - if (evt & USB_CHG_EVENT_VBUS) { - pi3usb9281_enable_interrupts(port); -#ifndef CONFIG_USB_PD_VBUS_DETECT_TCPC - CPRINTS("VBUS p%d %d", port, - pd_snk_is_vbus_provided(port)); -#endif - } - - evt = task_wait_event(-1); - } -} - -#if defined(CONFIG_CHARGE_RAMP_SW) || defined(CONFIG_CHARGE_RAMP_HW) -int usb_charger_ramp_allowed(int supplier) -{ - return supplier == CHARGE_SUPPLIER_BC12_DCP || - supplier == CHARGE_SUPPLIER_BC12_SDP || - supplier == CHARGE_SUPPLIER_BC12_CDP || - supplier == CHARGE_SUPPLIER_PROPRIETARY; -} - -int usb_charger_ramp_max(int supplier, int sup_curr) -{ - switch (supplier) { - case CHARGE_SUPPLIER_BC12_DCP: - return 2000; - case CHARGE_SUPPLIER_BC12_SDP: - return 1000; - case CHARGE_SUPPLIER_BC12_CDP: - case CHARGE_SUPPLIER_PROPRIETARY: - return sup_curr; - default: - return 500; - } -} -#endif /* CONFIG_CHARGE_RAMP_SW || CONFIG_CHARGE_RAMP_HW */ diff --git a/driver/build.mk b/driver/build.mk index a98eaa763c..5124b7c2d9 100644 --- a/driver/build.mk +++ b/driver/build.mk @@ -9,145 +9,10 @@ # Note that this variable includes the trailing "/" _driver_cur_dir:=$(dir $(lastword $(MAKEFILE_LIST))) -# Accelerometers -driver-$(CONFIG_ACCEL_BMA255)+=accel_bma2x2.o -driver-$(CONFIG_ACCEL_KXCJ9)+=accel_kionix.o -driver-$(CONFIG_ACCEL_KX022)+=accel_kionix.o -driver-$(CONFIG_ACCELGYRO_LSM6DS0)+=accelgyro_lsm6ds0.o -driver-$(CONFIG_ACCELGYRO_BMI160)+=accelgyro_bmi160.o -driver-$(CONFIG_MAG_BMI160_BMM150)+=mag_bmm150.o -driver-$(CONFIG_ACCELGYRO_LSM6DSM)+=accelgyro_lsm6dsm.o stm_mems_common.o -driver-$(CONFIG_ACCELGYRO_LSM6DSO)+=accelgyro_lsm6dso.o stm_mems_common.o -driver-$(CONFIG_ACCEL_LIS2D_COMMON)+=accel_lis2dh.o stm_mems_common.o -driver-$(CONFIG_MAG_LIS2MDL)+=mag_lis2mdl.o -driver-$(CONFIG_SENSORHUB_LSM6DSM)+=sensorhub_lsm6dsm.o -driver-$(CONFIG_SYNC)+=sync.o -driver-$(CONFIG_ACCEL_LIS2DW_COMMON)+=accel_lis2dw12.o stm_mems_common.o - -# BC1.2 Charger Detection Devices -driver-$(CONFIG_BC12_DETECT_MAX14637)+=bc12/max14637.o -driver-$(CONFIG_BC12_DETECT_PI3USB9201)+=bc12/pi3usb9201.o -driver-$(CONFIG_BC12_DETECT_PI3USB9281)+=bc12/pi3usb9281.o - -# Gyrometers -driver-$(CONFIG_GYRO_L3GD20H)+=gyro_l3gd20h.o - -# ALS drivers -driver-$(CONFIG_ALS_AL3010)+=als_al3010.o -driver-$(CONFIG_ALS_ISL29035)+=als_isl29035.o -driver-$(CONFIG_ALS_OPT3001)+=als_opt3001.o -driver-$(CONFIG_ALS_SI114X)+=als_si114x.o -driver-$(CONFIG_ALS_BH1730)+=als_bh1730.o -driver-$(CONFIG_ALS_TCS3400)+=als_tcs3400.o - -# Barometers -driver-$(CONFIG_BARO_BMP280)+=baro_bmp280.o - -# Batteries -driver-$(CONFIG_BATTERY_BQ20Z453)+=battery/bq20z453.o -driver-$(CONFIG_BATTERY_BQ27541)+=battery/bq27541.o -driver-$(CONFIG_BATTERY_BQ27621)+=battery/bq27621_g1.o -driver-$(CONFIG_BATTERY_MAX17055)+=battery/max17055.o -driver-$(CONFIG_BATTERY_SMART)+=battery/smart.o -driver-$(CONFIG_BATTERY_BQ4050)+=battery/bq4050.o -driver-$(CONFIG_BATTERY_MM8013)+=battery/mm8013.o - -# Battery charger ICs -driver-$(CONFIG_CHARGER_BD9995X)+=charger/bd9995x.o -driver-$(CONFIG_CHARGER_BQ24192)+=charger/bq24192.o -driver-$(CONFIG_CHARGER_BQ24707A)+=charger/bq24707a.o -driver-$(CONFIG_CHARGER_BQ24715)+=charger/bq24715.o -driver-$(CONFIG_CHARGER_BQ24725)+=charger/bq24725.o -driver-$(CONFIG_CHARGER_BQ24735)+=charger/bq24735.o -driver-$(CONFIG_CHARGER_BQ24738)+=charger/bq24738.o -driver-$(CONFIG_CHARGER_BQ24770)+=charger/bq24773.o -driver-$(CONFIG_CHARGER_BQ24773)+=charger/bq24773.o -driver-$(CONFIG_CHARGER_BQ25703)+=charger/bq25703.o -driver-$(CONFIG_CHARGER_BQ25710)+=charger/bq25710.o -driver-$(CONFIG_CHARGER_BQ25890)+=charger/bq2589x.o -driver-$(CONFIG_CHARGER_BQ25892)+=charger/bq2589x.o -driver-$(CONFIG_CHARGER_BQ25895)+=charger/bq2589x.o -driver-$(CONFIG_CHARGER_ISL9237)+=charger/isl923x.o -driver-$(CONFIG_CHARGER_ISL9238)+=charger/isl923x.o -driver-$(CONFIG_CHARGER_ISL9241)+=charger/isl9241.o -driver-$(CONFIG_CHARGER_MT6370)+=charger/rt946x.o -driver-$(CONFIG_CHARGER_RT9466)+=charger/rt946x.o -driver-$(CONFIG_CHARGER_RT9467)+=charger/rt946x.o -driver-$(CONFIG_CHARGER_SY21612)+=charger/sy21612.o - -# I/O expander -driver-$(CONFIG_IO_EXPANDER_IT8801)+=ioexpander/it8801.o -driver-$(CONFIG_IO_EXPANDER_PCA9534)+=ioexpander/pca9534.o -driver-$(CONFIG_IO_EXPANDER_NCT38XX)+=ioexpander/ioexpander_nct38xx.o - - # Current/Power monitor driver-$(CONFIG_INA219)$(CONFIG_INA231)+=ina2xx.o driver-$(CONFIG_INA3221)+=ina3221.o -# LED drivers -driver-$(CONFIG_LED_DRIVER_DS2413)+=led/ds2413.o -driver-$(CONFIG_LED_DRIVER_LM3509)+=led/lm3509.o -driver-$(CONFIG_LED_DRIVER_LM3630A)+=led/lm3630a.o -driver-$(CONFIG_LED_DRIVER_LP5562)+=led/lp5562.o -driver-$(CONFIG_LED_DRIVER_OZ554)+=led/oz554.o - -# 7-segment display -driver-$(CONFIG_MAX695X_SEVEN_SEGMENT_DISPLAY)+=led/max695x.o - -# Voltage regulators -driver-$(CONFIG_REGULATOR_IR357X)+=regulator_ir357x.o - -# Temperature sensors -driver-$(CONFIG_TEMP_SENSOR_ADT7481)+=temp_sensor/adt7481.o -driver-$(CONFIG_TEMP_SENSOR_BD99992GW)+=temp_sensor/bd99992gw.o -driver-$(CONFIG_TEMP_SENSOR_EC_ADC)+=temp_sensor/ec_adc.o -driver-$(CONFIG_TEMP_SENSOR_F75303)+=temp_sensor/f75303.o -driver-$(CONFIG_TEMP_SENSOR_G753)+=temp_sensor/g753.o -driver-$(CONFIG_TEMP_SENSOR_G781)+=temp_sensor/g78x.o -driver-$(CONFIG_TEMP_SENSOR_G782)+=temp_sensor/g78x.o -driver-$(CONFIG_TEMP_SENSOR_SB_TSI)+=temp_sensor/sb_tsi.o -driver-$(CONFIG_TEMP_SENSOR_TMP006)+=temp_sensor/tmp006.o -driver-$(CONFIG_TEMP_SENSOR_TMP112)+=temp_sensor/tmp112.o -driver-$(CONFIG_TEMP_SENSOR_TMP411)+=temp_sensor/tmp411.o -driver-$(CONFIG_TEMP_SENSOR_TMP432)+=temp_sensor/tmp432.o -driver-$(CONFIG_TEMP_SENSOR_TMP468)+=temp_sensor/tmp468.o - -# Touchpads -driver-$(CONFIG_TOUCHPAD_GT7288)+=touchpad_gt7288.o -driver-$(CONFIG_TOUCHPAD_ELAN)+=touchpad_elan.o -driver-$(CONFIG_TOUCHPAD_ST)+=touchpad_st.o - # Thermistors driver-$(CONFIG_THERMISTOR)+=temp_sensor/thermistor.o driver-$(CONFIG_THERMISTOR_NCP15WB)+=temp_sensor/thermistor_ncp15wb.o - -# Type-C Retimer drivers -driver-$(CONFIG_USBC_RETIMER_INTEL_BB)+=retimer/bb_retimer.o -driver-$(CONFIG_USBC_RETIMER_PI3DPX1207)+=retimer/pi3dpx1207.o - -# USB mux high-level driver -driver-$(CONFIG_USBC_SS_MUX)+=usb_mux/usb_mux.o - -# USB muxes -driver-$(CONFIG_USB_MUX_AMD_FP5)+=usb_mux/amd_fp5.o -driver-$(CONFIG_USB_MUX_IT5205)+=usb_mux/it5205.o -driver-$(CONFIG_USB_MUX_PI3USB30532)+=usb_mux/pi3usb30532.o -driver-$(CONFIG_USB_MUX_PS8740)+=usb_mux/ps874x.o -driver-$(CONFIG_USB_MUX_PS8743)+=usb_mux/ps874x.o -driver-$(CONFIG_USB_MUX_VIRTUAL)+=usb_mux/virtual.o - -# Type-C Power Path Controllers (PPC) -driver-$(CONFIG_USBC_PPC_AOZ1380)+=ppc/aoz1380.o -driver-$(CONFIG_USBC_PPC_SN5S330)+=ppc/sn5s330.o -ifeq ($(CONFIG_USBC_PPC_NX20P3481)$(CONFIG_USBC_PPC_NX20P3483),y) -driver-y += ppc/nx20p348x.o -endif -driver-$(CONFIG_USBC_PPC_SYV682X)+=ppc/syv682x.o -driver-$(CONFIG_USBC_PPC_NX20P3483)+=ppc/nx20p348x.o - -# video converters -driver-$(CONFIG_MCDP28X0)+=mcdp28x0.o - -# Wireless Power Chargers -driver-$(HAS_TASK_WPC) += wpc/p9221.o diff --git a/driver/charger/bd9995x.c b/driver/charger/bd9995x.c deleted file mode 100644 index 23303589b6..0000000000 --- a/driver/charger/bd9995x.c +++ /dev/null @@ -1,1674 +0,0 @@ -/* 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. - * - * ROHM BD9995X battery charger driver. - */ - -#include "battery.h" -#include "battery_smart.h" -#include "bd9995x.h" -#include "charge_manager.h" -#include "charge_state.h" -#include "charger.h" -#include "console.h" -#include "ec_commands.h" -#include "hooks.h" -#include "i2c.h" -#include "task.h" -#include "time.h" -#include "util.h" -#include "usb_charge.h" -#include "usb_pd.h" - -#define OTPROM_LOAD_WAIT_RETRY 3 - -#define BD9995X_CHARGE_PORT_COUNT 2 - -/* - * BC1.2 detection starts 100ms after VBUS/VCC attach and typically - * completes 312ms after VBUS/VCC attach. - */ -#define BC12_DETECT_US (312*MSEC) -#define BD9995X_VSYS_PRECHARGE_OFFSET_MV 200 - -/* Console output macros */ -#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ## args) - -#ifdef CONFIG_BD9995X_DELAY_INPUT_PORT_SELECT -/* - * Used in a check to determine if VBUS is within the - * range of some VOLTAGE +/- VBUS_DELTA, where voltage - * is measured in mV. - */ -#define VBUS_DELTA 1000 - -/* VBUS is debounced if it's stable for this length of time */ -#define VBUS_MSEC (100*MSEC) - -/* VBUS debouncing sample interval */ -#define VBUS_CHECK_MSEC (10*MSEC) - -/* Time to wait before VBUS debouncing begins */ -#define STABLE_TIMEOUT (500*MSEC) - -/* Maximum time to wait until VBUS is debounced */ -#define DEBOUNCE_TIMEOUT (500*MSEC) - -enum vstate {START, STABLE, DEBOUNCE}; -static enum vstate vbus_state; - -static int vbus_voltage; -static uint64_t debounce_time; -static uint64_t vbus_timeout; -static int port_update; -static int select_update; -static int select_input_port_update; -#endif - -/* Charger parameters */ -static const struct charger_info bd9995x_charger_info = { - .name = CHARGER_NAME, - .voltage_max = CHARGE_V_MAX, - .voltage_min = CHARGE_V_MIN, - .voltage_step = CHARGE_V_STEP, - .current_max = CHARGE_I_MAX, - .current_min = CHARGE_I_MIN, - .current_step = CHARGE_I_STEP, - .input_current_max = INPUT_I_MAX, - .input_current_min = INPUT_I_MIN, - .input_current_step = INPUT_I_STEP, -}; - -/* Charge command code map */ -static enum bd9995x_command charger_map_cmd = BD9995X_INVALID_COMMAND; - -/* Mutex for active register set control. */ -static struct mutex bd9995x_map_mutex; - -/* Tracks the state of VSYS_PRIORITY */ -static int vsys_priority; -/* Mutex for VIN_CTRL_SET register */ -static struct mutex bd9995x_vin_mutex; - -#ifdef HAS_TASK_USB_CHG -/* USB switch */ -static enum usb_switch usb_switch_state[BD9995X_CHARGE_PORT_COUNT] = { - USB_SWITCH_DISCONNECT, - USB_SWITCH_DISCONNECT, -}; - -static int bd9995x_get_bc12_ilim(int charge_supplier) -{ - switch (charge_supplier) { - case CHARGE_SUPPLIER_BC12_CDP: - return 1500; - case CHARGE_SUPPLIER_BC12_DCP: - return 2000; - case CHARGE_SUPPLIER_BC12_SDP: - return 900; - case CHARGE_SUPPLIER_OTHER: -#ifdef CONFIG_CHARGE_RAMP_SW - return 2400; -#else - /* - * Setting the higher limit of current may result in an - * anti-collapse hence limiting the current to 1A. - */ - return 1000; -#endif - default: - return 500; - } -} -#endif /* HAS_TASK_USB_CHG */ - -static inline int ch_raw_read16(int cmd, int *param, - enum bd9995x_command map_cmd) -{ - int rv; - - /* Map the Charge command code to appropriate region */ - mutex_lock(&bd9995x_map_mutex); - if (charger_map_cmd != map_cmd) { - rv = i2c_write16(I2C_PORT_CHARGER, I2C_ADDR_CHARGER_FLAGS, - BD9995X_CMD_MAP_SET, map_cmd); - if (rv) { - charger_map_cmd = BD9995X_INVALID_COMMAND; - goto bd9995x_read_cleanup; - } - - charger_map_cmd = map_cmd; - } - - rv = i2c_read16(I2C_PORT_CHARGER, I2C_ADDR_CHARGER_FLAGS, - cmd, param); - -bd9995x_read_cleanup: - mutex_unlock(&bd9995x_map_mutex); - - return rv; -} - -static inline int ch_raw_write16(int cmd, int param, - enum bd9995x_command map_cmd) -{ - int rv; - - /* Map the Charge command code to appropriate region */ - mutex_lock(&bd9995x_map_mutex); - if (charger_map_cmd != map_cmd) { - rv = i2c_write16(I2C_PORT_CHARGER, I2C_ADDR_CHARGER_FLAGS, - BD9995X_CMD_MAP_SET, map_cmd); - if (rv) { - charger_map_cmd = BD9995X_INVALID_COMMAND; - goto bd9995x_write_cleanup; - } - - charger_map_cmd = map_cmd; - } - - rv = i2c_write16(I2C_PORT_CHARGER, I2C_ADDR_CHARGER_FLAGS, - cmd, param); - -bd9995x_write_cleanup: - mutex_unlock(&bd9995x_map_mutex); - - return rv; -} - -/* BD9995X local interfaces */ - -static int bd9995x_set_vfastchg(int voltage) -{ - - int rv; - - /* Fast Charge Voltage Regulation Settings for fast charging. */ - rv = ch_raw_write16(BD9995X_CMD_VFASTCHG_REG_SET1, - voltage & 0x7FF0, BD9995X_EXTENDED_COMMAND); - if (rv) - return rv; - -#ifndef CONFIG_CHARGER_BATTERY_TSENSE - /* - * If TSENSE is not connected set all the VFASTCHG_REG_SETx - * to same voltage. - */ - rv = ch_raw_write16(BD9995X_CMD_VFASTCHG_REG_SET2, - voltage & 0x7FF0, BD9995X_EXTENDED_COMMAND); - if (rv) - return rv; - - rv = ch_raw_write16(BD9995X_CMD_VFASTCHG_REG_SET3, - voltage & 0x7FF0, BD9995X_EXTENDED_COMMAND); -#endif - - return rv; -} - -static int bd9995x_set_vsysreg(int voltage) -{ - /* VSYS Regulation voltage is in 64mV steps. */ - voltage &= ~0x3F; - - return ch_raw_write16(BD9995X_CMD_VSYSREG_SET, voltage, - BD9995X_EXTENDED_COMMAND); -} - -static int bd9995x_is_discharging_on_ac(void) -{ - int reg; - - if (ch_raw_read16(BD9995X_CMD_CHGOP_SET2, ®, - BD9995X_EXTENDED_COMMAND)) - return 0; - - return !!(reg & BD9995X_CMD_CHGOP_SET2_BATT_LEARN); -} - -static int bd9995x_charger_enable(int enable) -{ - int rv, reg; - static int prev_chg_enable = -1; - const struct battery_info *bi = battery_get_info(); - -#ifdef CONFIG_CHARGER_BD9995X_CHGEN - /* - * If the battery is not yet initialized, dont turn-off the BGATE so - * that voltage from the AC is applied to the battery PACK. - */ - if (!enable && !board_battery_initialized()) - return EC_SUCCESS; -#endif - - /* Nothing to change */ - if (enable == prev_chg_enable) - return EC_SUCCESS; - - prev_chg_enable = enable; - - if (enable) { - /* - * BGATE capacitor max : 0.1uF + 20% - * Charge MOSFET threshold max : 2.8V - * BGATE charge pump current min : 3uA - * T = C * V / I so, Tmax = 112ms - */ - msleep(115); - - /* - * Set VSYSREG_SET <= VBAT so that the charger is in Fast-Charge - * state when charging. - */ - rv = bd9995x_set_vsysreg(bi->voltage_min); - } else { - /* - * Set VSYSREG_SET > VBAT so that the charger is in Pre-Charge - * state when not charging or discharging. - */ - rv = bd9995x_set_vsysreg(bi->voltage_max + - BD9995X_VSYS_PRECHARGE_OFFSET_MV); - - /* - * Allow charger in pre-charge state for 50ms before disabling - * the charger which prevents inrush current while moving from - * fast-charge state to pre-charge state. - */ - msleep(50); - } - if (rv) - return rv; - - rv = ch_raw_read16(BD9995X_CMD_CHGOP_SET2, ®, - BD9995X_EXTENDED_COMMAND); - if (rv) - return rv; - - if (enable) - reg |= BD9995X_CMD_CHGOP_SET2_CHG_EN; - else - reg &= ~BD9995X_CMD_CHGOP_SET2_CHG_EN; - - return ch_raw_write16(BD9995X_CMD_CHGOP_SET2, reg, - BD9995X_EXTENDED_COMMAND); -} - -static int bd9995x_por_reset(void) -{ - int rv; - int reg; - int i; - - rv = ch_raw_write16(BD9995X_CMD_SYSTEM_CTRL_SET, - BD9995X_CMD_SYSTEM_CTRL_SET_OTPLD | - BD9995X_CMD_SYSTEM_CTRL_SET_ALLRST, - BD9995X_EXTENDED_COMMAND); - if (rv) - return rv; - - /* Wait until OTPROM loading is finished */ - for (i = 0; i < OTPROM_LOAD_WAIT_RETRY; i++) { - msleep(10); - rv = ch_raw_read16(BD9995X_CMD_SYSTEM_STATUS, ®, - BD9995X_EXTENDED_COMMAND); - - if (!rv && (reg & BD9995X_CMD_SYSTEM_STATUS_OTPLD_STATE) && - (reg & BD9995X_CMD_SYSTEM_STATUS_ALLRST_STATE)) - break; - } - - if (rv) - return rv; - if (i == OTPROM_LOAD_WAIT_RETRY) - return EC_ERROR_TIMEOUT; - - return ch_raw_write16(BD9995X_CMD_SYSTEM_CTRL_SET, 0, - BD9995X_EXTENDED_COMMAND); -} - -static int bd9995x_reset_to_zero(void) -{ - int rv; - - rv = charger_set_current(0); - if (rv) - return rv; - - return charger_set_voltage(0); -} - -static int bd9995x_get_charger_op_status(int *status) -{ - return ch_raw_read16(BD9995X_CMD_CHGOP_STATUS, status, - BD9995X_EXTENDED_COMMAND); -} - -#ifdef HAS_TASK_USB_CHG -static int bc12_detected_type[CONFIG_USB_PD_PORT_MAX_COUNT]; -/* Mutex for UCD_SET regsiters, lock before read / mask / write. */ -static struct mutex ucd_set_mutex[BD9995X_CHARGE_PORT_COUNT]; - -static int bd9995x_get_bc12_device_type(int port) -{ - int rv; - int reg; - - rv = ch_raw_read16((port == BD9995X_CHARGE_PORT_VBUS) ? - BD9995X_CMD_VBUS_UCD_STATUS : - BD9995X_CMD_VCC_UCD_STATUS, - ®, BD9995X_EXTENDED_COMMAND); - if (rv) - return CHARGE_SUPPLIER_NONE; - - switch (reg & BD9995X_TYPE_MASK) { - case BD9995X_TYPE_CDP: - return CHARGE_SUPPLIER_BC12_CDP; - case BD9995X_TYPE_DCP: - return CHARGE_SUPPLIER_BC12_DCP; - case BD9995X_TYPE_SDP: - return CHARGE_SUPPLIER_BC12_SDP; - case BD9995X_TYPE_PUP_PORT: - case BD9995X_TYPE_OTHER: - return CHARGE_SUPPLIER_OTHER; - case BD9995X_TYPE_OPEN_PORT: - case BD9995X_TYPE_VBUS_OPEN: - default: - return CHARGE_SUPPLIER_NONE; - } -} - -/* - * Do safe read / mask / write of BD9995X_CMD_*_UCD_SET register. - * The USB charger task owns all bits of this register, except for bit 0 - * (BD9995X_CMD_UCD_SET_USB_SW), which is controlled by - * usb_charger_set_switches(). - */ -static int bd9995x_update_ucd_set_reg(int port, uint16_t mask, int set) -{ - int rv; - int reg; - int port_reg = (port == BD9995X_CHARGE_PORT_VBUS) ? - BD9995X_CMD_VBUS_UCD_SET : BD9995X_CMD_VCC_UCD_SET; - - mutex_lock(&ucd_set_mutex[port]); - rv = ch_raw_read16(port_reg, ®, BD9995X_EXTENDED_COMMAND); - if (!rv) { - if (set) - reg |= mask; - else - reg &= ~mask; - - rv = ch_raw_write16(port_reg, reg, BD9995X_EXTENDED_COMMAND); - } - - mutex_unlock(&ucd_set_mutex[port]); - return rv; -} - -static int bd9995x_bc12_check_type(int port) -{ - int bc12_type; - struct charge_port_info charge; - int vbus_provided = bd9995x_is_vbus_provided(port) && - !usb_charger_port_is_sourcing_vbus(port); - - /* - * If vbus is no longer provided, then no need to continue. Return 0 so - * that a wait event is not scheduled. - */ - if (!vbus_provided) - return 0; - - /* get device type */ - bc12_type = bd9995x_get_bc12_device_type(port); - if (bc12_type == CHARGE_SUPPLIER_NONE) - /* - * Device type is not available, return non-zero so new wait - * will be scheduled before putting the task to sleep. - */ - return 1; - - bc12_detected_type[port] = bc12_type; - /* Update charge manager */ - charge.voltage = USB_CHARGER_VOLTAGE_MV; - charge.current = bd9995x_get_bc12_ilim(bc12_type); - charge_manager_update_charge(bc12_type, port, &charge); - - return 0; -} - -static void bd9995x_bc12_detach(int port, int type) -{ - /* Update charge manager */ - charge_manager_update_charge(type, port, NULL); - - /* Disable charging trigger by BC1.2 detection */ - bd9995x_bc12_enable_charging(port, 0); -} - -static int bd9995x_enable_vbus_detect_interrupts(int port, int enable) -{ - int reg; - int rv; - int port_reg; - int mask_val; - - /* 1st Level Interrupt Setting */ - rv = ch_raw_read16(BD9995X_CMD_INT0_SET, ®, - BD9995X_EXTENDED_COMMAND); - if (rv) - return rv; - - mask_val = ((port == BD9995X_CHARGE_PORT_VBUS) ? - BD9995X_CMD_INT0_SET_INT1_EN : - BD9995X_CMD_INT0_SET_INT2_EN) | - BD9995X_CMD_INT0_SET_INT0_EN; - if (enable) - reg |= mask_val; - else - reg &= ~mask_val; - - rv = ch_raw_write16(BD9995X_CMD_INT0_SET, reg, - BD9995X_EXTENDED_COMMAND); - if (rv) - return rv; - - /* 2nd Level Interrupt Setting */ - port_reg = (port == BD9995X_CHARGE_PORT_VBUS) ? - BD9995X_CMD_INT1_SET : BD9995X_CMD_INT2_SET; - rv = ch_raw_read16(port_reg, ®, BD9995X_EXTENDED_COMMAND); - if (rv) - return rv; - - /* Enable threshold interrupts if we need to control discharge */ -#ifdef CONFIG_USB_PD_DISCHARGE - mask_val = BD9995X_CMD_INT_VBUS_DET | BD9995X_CMD_INT_VBUS_TH; -#else - mask_val = BD9995X_CMD_INT_VBUS_DET; -#endif - if (enable) - reg |= mask_val; - else - reg &= ~mask_val; - - return ch_raw_write16(port_reg, reg, BD9995X_EXTENDED_COMMAND); -} - -/* Read + clear active interrupt bits for a given port */ -static int bd9995x_get_interrupts(int port) -{ - int rv; - int reg; - int port_reg; - - port_reg = (port == BD9995X_CHARGE_PORT_VBUS) ? - BD9995X_CMD_INT1_STATUS : BD9995X_CMD_INT2_STATUS; - - rv = ch_raw_read16(port_reg, ®, BD9995X_EXTENDED_COMMAND); - - if (rv) - return 0; - - /* Clear the interrupt status bits we just read */ - ch_raw_write16(port_reg, reg, BD9995X_EXTENDED_COMMAND); - - return reg; -} - -/* - * Set or clear registers necessary to do one-time BC1.2 detection. - * Pass enable = 1 to trigger BC1.2 detection, and enable = 0 once - * BC1.2 detection has completed. - */ -static int bd9995x_bc12_detect(int port, int enable) -{ - return bd9995x_update_ucd_set_reg(port, - BD9995X_CMD_UCD_SET_BCSRETRY | - BD9995X_CMD_UCD_SET_USBDETEN | - BD9995X_CMD_UCD_SET_USB_SW_EN, - enable); -} - -static int usb_charger_process(int port) -{ - int vbus_provided = bd9995x_is_vbus_provided(port) && - !usb_charger_port_is_sourcing_vbus(port); - - /* Inform other modules about VBUS level */ - usb_charger_vbus_change(port, vbus_provided); - - /* - * Do BC1.2 detection, if we have VBUS and our port is not known - * to speak PD. - */ - if (vbus_provided && !pd_capable(port)) { - bd9995x_bc12_detect(port, 1); - /* - * Need to give the charger time (~312 mSec) before the - * bc12_type is available. The main task loop will schedule a - * task wait event which will then call bd9995x_bc12_get_type. - */ - return 1; - } - - /* Reset BC1.2 regs so we don't do auto-detection. */ - bd9995x_bc12_detect(port, 0); - - /* - * VBUS is no longer being provided, if the bc12_type had been - * previously determined, then need to detach. - */ - if (bc12_detected_type[port] != CHARGE_SUPPLIER_NONE) { - /* Charger/sink detached */ - bd9995x_bc12_detach(port, bc12_detected_type[port]); - bc12_detected_type[port] = CHARGE_SUPPLIER_NONE; - } - /* No need for the task to schedule a wait event */ - return 0; -} - -#ifdef CONFIG_CHARGE_RAMP_SW -int usb_charger_ramp_allowed(int supplier) -{ - return supplier == CHARGE_SUPPLIER_BC12_DCP || - supplier == CHARGE_SUPPLIER_BC12_SDP || - supplier == CHARGE_SUPPLIER_BC12_CDP || - supplier == CHARGE_SUPPLIER_OTHER; -} - -int usb_charger_ramp_max(int supplier, int sup_curr) -{ - return bd9995x_get_bc12_ilim(supplier); -} -#endif /* CONFIG_CHARGE_RAMP_SW */ -#endif /* HAS_TASK_USB_CHG */ - -/* chip specific interfaces */ - -int charger_set_input_current(int input_current) -{ - int rv; - - /* Input current step 32 mA */ - input_current &= ~0x1F; - - if (input_current < bd9995x_charger_info.input_current_min) - input_current = bd9995x_charger_info.input_current_min; - - rv = ch_raw_write16(BD9995X_CMD_IBUS_LIM_SET, input_current, - BD9995X_BAT_CHG_COMMAND); - if (rv) - return rv; - - return ch_raw_write16(BD9995X_CMD_ICC_LIM_SET, input_current, - BD9995X_BAT_CHG_COMMAND); -} - -int charger_get_input_current(int *input_current) -{ - return ch_raw_read16(BD9995X_CMD_CUR_ILIM_VAL, input_current, - BD9995X_EXTENDED_COMMAND); -} - -int charger_manufacturer_id(int *id) -{ - return EC_ERROR_UNIMPLEMENTED; -} - -int charger_device_id(int *id) -{ - return ch_raw_read16(BD9995X_CMD_CHIP_ID, id, BD9995X_EXTENDED_COMMAND); -} - -int charger_get_option(int *option) -{ - int rv; - int reg; - - rv = ch_raw_read16(BD9995X_CMD_CHGOP_SET1, option, - BD9995X_EXTENDED_COMMAND); - if (rv) - return rv; - - rv = ch_raw_read16(BD9995X_CMD_CHGOP_SET2, ®, - BD9995X_EXTENDED_COMMAND); - if (rv) - return rv; - - *option |= reg << 16; - - return EC_SUCCESS; -} - -int charger_set_option(int option) -{ - int rv; - - rv = ch_raw_write16(BD9995X_CMD_CHGOP_SET1, option & 0xFFFF, - BD9995X_EXTENDED_COMMAND); - if (rv) - return rv; - - return ch_raw_write16(BD9995X_CMD_CHGOP_SET2, (option >> 16) & 0xFFFF, - BD9995X_EXTENDED_COMMAND); -} - -/* Charger interfaces */ - -const struct charger_info *charger_get_info(void) -{ - return &bd9995x_charger_info; -} - -int charger_get_status(int *status) -{ - int rv; - int reg; - int ch_status; - - /* charger level */ - *status = CHARGER_LEVEL_2; - - /* charger enable/inhibit */ - rv = ch_raw_read16(BD9995X_CMD_CHGOP_SET2, ®, - BD9995X_EXTENDED_COMMAND); - if (rv) - return rv; - - if (!(reg & BD9995X_CMD_CHGOP_SET2_CHG_EN)) - *status |= CHARGER_CHARGE_INHIBITED; - - /* charger alarm enable/inhibit */ - rv = ch_raw_read16(BD9995X_CMD_PROCHOT_CTRL_SET, ®, - BD9995X_EXTENDED_COMMAND); - if (rv) - return rv; - - if (!(reg & (BD9995X_CMD_PROCHOT_CTRL_SET_PROCHOT_EN4 | - BD9995X_CMD_PROCHOT_CTRL_SET_PROCHOT_EN3 | - BD9995X_CMD_PROCHOT_CTRL_SET_PROCHOT_EN2 | - BD9995X_CMD_PROCHOT_CTRL_SET_PROCHOT_EN1 | - BD9995X_CMD_PROCHOT_CTRL_SET_PROCHOT_EN0))) - *status |= CHARGER_ALARM_INHIBITED; - - rv = bd9995x_get_charger_op_status(®); - if (rv) - return rv; - - /* power fail */ - if (!(reg & BD9995X_CMD_CHGOP_STATUS_RBOOST_UV)) - *status |= CHARGER_POWER_FAIL; - - /* Safety signal ranges & battery presence */ - ch_status = (reg & BD9995X_BATTTEMP_MASK) >> 8; - - *status |= CHARGER_BATTERY_PRESENT; - - switch (ch_status) { - case BD9995X_CMD_CHGOP_STATUS_BATTEMP_COLD1: - *status |= CHARGER_RES_COLD; - break; - case BD9995X_CMD_CHGOP_STATUS_BATTEMP_COLD2: - *status |= CHARGER_RES_COLD; - *status |= CHARGER_RES_UR; - break; - case BD9995X_CMD_CHGOP_STATUS_BATTEMP_HOT1: - case BD9995X_CMD_CHGOP_STATUS_BATTEMP_HOT2: - *status |= CHARGER_RES_HOT; - break; - case BD9995X_CMD_CHGOP_STATUS_BATTEMP_HOT3: - *status |= CHARGER_RES_HOT; - *status |= CHARGER_RES_OR; - break; - case BD9995X_CMD_CHGOP_STATUS_BATTEMP_BATOPEN: - *status &= ~CHARGER_BATTERY_PRESENT; - default: - break; - } - - /* source of power */ - if (bd9995x_is_vbus_provided(BD9995X_CHARGE_PORT_BOTH)) - *status |= CHARGER_AC_PRESENT; - - return EC_SUCCESS; -} - -int charger_set_mode(int mode) -{ - int rv; - - if (mode & CHARGE_FLAG_POR_RESET) { - rv = bd9995x_por_reset(); - if (rv) - return rv; - } - - if (mode & CHARGE_FLAG_RESET_TO_ZERO) { - rv = bd9995x_reset_to_zero(); - if (rv) - return rv; - } - - return EC_SUCCESS; -} - -int charger_get_current(int *current) -{ - return ch_raw_read16(BD9995X_CMD_CHG_CURRENT, current, - BD9995X_BAT_CHG_COMMAND); -} - -int charger_set_current(int current) -{ - int rv; - int chg_enable = 1; - - /* Charge current step 64 mA */ - current &= ~0x3F; - - if (current < BD9995X_NO_BATTERY_CHARGE_I_MIN && - (battery_is_present() != BP_YES || battery_is_cut_off())) - current = BD9995X_NO_BATTERY_CHARGE_I_MIN; - - /* - * Disable charger before setting charge current to 0 or when - * discharging on AC. - * If charging current is set to 0mA during charging, reference of - * the charge current feedback amp (VREF_CHG) is set to 0V. Hence - * the DCDC stops switching (because of the EA offset). - */ - if (!current || bd9995x_is_discharging_on_ac()) { - chg_enable = 0; - rv = bd9995x_charger_enable(0); - if (rv) - return rv; - } - - rv = ch_raw_write16(BD9995X_CMD_IPRECH_SET, - MIN(current, BD9995X_IPRECH_MAX), - BD9995X_EXTENDED_COMMAND); - if (rv) - return rv; - - rv = ch_raw_write16(BD9995X_CMD_CHG_CURRENT, current, - BD9995X_BAT_CHG_COMMAND); - if (rv) - return rv; - - /* - * Enable charger if charge current is non-zero or not discharging - * on AC. - */ - return chg_enable ? bd9995x_charger_enable(1) : EC_SUCCESS; -} - -int charger_get_voltage(int *voltage) -{ - if (vsys_priority) { - int batt_volt_measured; - int reg; - int rv; - - /* Get battery voltage as reported by charger */ - batt_volt_measured = bd9995x_get_battery_voltage(); - if (batt_volt_measured > (battery_get_info()->voltage_min + - BD9995X_VSYS_PRECHARGE_OFFSET_MV)) { - /* - * Battery is not deeply discharged. Clear the - * VSYS_PRIORITY bit to ensure that input current limit - * is always active. - */ - mutex_lock(&bd9995x_vin_mutex); - if (!ch_raw_read16(BD9995X_CMD_VIN_CTRL_SET, ®, - BD9995X_EXTENDED_COMMAND)) { - reg &= ~BD9995X_CMD_VIN_CTRL_SET_VSYS_PRIORITY; - rv = ch_raw_write16(BD9995X_CMD_VIN_CTRL_SET, - reg, - BD9995X_EXTENDED_COMMAND); - - /* Mirror the state of this bit */ - if (!rv) - vsys_priority = 0; - } - mutex_unlock(&bd9995x_vin_mutex); - } - } - - return ch_raw_read16(BD9995X_CMD_CHG_VOLTAGE, voltage, - BD9995X_BAT_CHG_COMMAND); -} - -int charger_set_voltage(int voltage) -{ - const int battery_voltage_max = battery_get_info()->voltage_max; - - /* - * Regulate the system voltage to battery max if the battery - * is not present or the battery is discharging on AC. - */ - if (voltage == 0 || - bd9995x_is_discharging_on_ac() || - battery_is_present() != BP_YES || - battery_is_cut_off() || - voltage > battery_voltage_max) - voltage = battery_voltage_max; - - /* Charge voltage step 16 mV */ - voltage &= ~0x0F; - - /* Assumes charger's voltage_min < battery's voltage_max */ - if (voltage < bd9995x_charger_info.voltage_min) - voltage = bd9995x_charger_info.voltage_min; - - return bd9995x_set_vfastchg(voltage); -} - -static void bd9995x_battery_charging_profile_settings(void) -{ - const struct battery_info *bi = battery_get_info(); - - /* Input Current Limit Setting */ - charger_set_input_current(CONFIG_CHARGER_INPUT_CURRENT); - - /* Charge Termination Current Setting */ - ch_raw_write16(BD9995X_CMD_ITERM_SET, 0, BD9995X_EXTENDED_COMMAND); - - /* Trickle-charge Current Setting */ - ch_raw_write16(BD9995X_CMD_ITRICH_SET, - bi->precharge_current & 0x07C0, - BD9995X_EXTENDED_COMMAND); - - bd9995x_set_vfastchg(bi->voltage_max); - - /* Set Pre-charge Voltage Threshold for trickle charging. */ - ch_raw_write16(BD9995X_CMD_VPRECHG_TH_SET, - (bi->voltage_min - 1000) & 0x7FC0, - BD9995X_EXTENDED_COMMAND); - - /* Re-charge Battery Voltage Setting */ - ch_raw_write16(BD9995X_CMD_VRECHG_SET, - bi->voltage_max & 0x7FF0, - BD9995X_EXTENDED_COMMAND); - - /* Set battery OVP to 500 + maximum battery voltage */ - ch_raw_write16(BD9995X_CMD_VBATOVP_SET, - (bi->voltage_max + 500) & 0x7ff0, - BD9995X_EXTENDED_COMMAND); - - /* Reverse buck boost voltage Setting */ - ch_raw_write16(BD9995X_CMD_VRBOOST_SET, 0, - BD9995X_EXTENDED_COMMAND); - - /* Disable fast/pre-charging watchdog */ - ch_raw_write16(BD9995X_CMD_CHGWDT_SET, 0, - BD9995X_EXTENDED_COMMAND); - - /* TODO(crosbug.com/p/55626): Set VSYSVAL_THH/THL appropriately */ -} - -static void bd9995x_init(void) -{ - int reg; - - /* - * Disable charging trigger by BC1.2 on VCC & VBUS and - * automatic limitation of the input current. - */ - if (ch_raw_read16(BD9995X_CMD_CHGOP_SET1, ®, - BD9995X_EXTENDED_COMMAND)) - return; - reg |= (BD9995X_CMD_CHGOP_SET1_SDP_CHG_TRIG_EN | - BD9995X_CMD_CHGOP_SET1_SDP_CHG_TRIG | - BD9995X_CMD_CHGOP_SET1_VBUS_BC_DISEN | - BD9995X_CMD_CHGOP_SET1_VCC_BC_DISEN | - BD9995X_CMD_CHGOP_SET1_ILIM_AUTO_DISEN | - BD9995X_CMD_CHGOP_SET1_SDP_500_SEL | - BD9995X_CMD_CHGOP_SET1_DCP_2500_SEL); - ch_raw_write16(BD9995X_CMD_CHGOP_SET1, reg, - BD9995X_EXTENDED_COMMAND); - - /* - * OTP setting for this register is 6.08V. Set VSYS to above battery max - * (as is done when charger is disabled) to ensure VSYSREG_SET > VBAT so - * that the charger is in Pre-Charge state and that the input current - * disable setting below will be active. - */ - bd9995x_set_vsysreg(battery_get_info()->voltage_max + - BD9995X_VSYS_PRECHARGE_OFFSET_MV); - - /* Enable BC1.2 USB charging and DC/DC converter @ 1200KHz */ - if (ch_raw_read16(BD9995X_CMD_CHGOP_SET2, ®, - BD9995X_EXTENDED_COMMAND)) - return; - reg &= ~(BD9995X_CMD_CHGOP_SET2_USB_SUS | - BD9995X_CMD_CHGOP_SET2_DCDC_CLK_SEL); - reg |= BD9995X_CMD_CHGOP_SET2_DCDC_CLK_SEL_1200; -#ifdef CONFIG_CHARGER_BD9995X_CHGEN - reg |= BD9995X_CMD_CHGOP_SET2_CHG_EN; -#endif - ch_raw_write16(BD9995X_CMD_CHGOP_SET2, reg, - BD9995X_EXTENDED_COMMAND); - - /* - * We disable IADP (here before setting IBUS_LIM_SET and ICC_LIM_SET) - * to prevent voltage on IADP/RESET pin from affecting SEL_ILIM_VAL. - */ - if (ch_raw_read16(BD9995X_CMD_VM_CTRL_SET, ®, - BD9995X_EXTENDED_COMMAND)) - return; - reg &= ~BD9995X_CMD_VM_CTRL_SET_EXTIADPEN; - ch_raw_write16(BD9995X_CMD_VM_CTRL_SET, reg, BD9995X_EXTENDED_COMMAND); - /* - * Disable the input current limit when VBAT is < VSYSREG_SET. This - * needs to be done before calling - * bd9995x_battery_charging_profile_settings() as in that function the - * input current limit is set to CONFIG_CHARGER_INPUT_CURRENT which is - * 512 mA. In deeply discharged battery cases, setting the input current - * limit this low can cause VSYS to collapse, which in turn can cause - * the EC's brownout detector to reset the EC. - */ - if (ch_raw_read16(BD9995X_CMD_VIN_CTRL_SET, ®, - BD9995X_EXTENDED_COMMAND)) - return; - reg |= BD9995X_CMD_VIN_CTRL_SET_VSYS_PRIORITY; - ch_raw_write16(BD9995X_CMD_VIN_CTRL_SET, reg, - BD9995X_EXTENDED_COMMAND); - /* Mirror the state of this bit */ - vsys_priority = 1; - - /* Define battery charging profile */ - bd9995x_battery_charging_profile_settings(); - - /* Power save mode when VBUS/VCC is removed. */ -#ifdef CONFIG_BD9995X_POWER_SAVE_MODE - bd9995x_set_power_save_mode(CONFIG_BD9995X_POWER_SAVE_MODE); -#else - bd9995x_set_power_save_mode(BD9995X_PWR_SAVE_OFF); -#endif - -#ifdef CONFIG_USB_PD_DISCHARGE - /* Set VBUS / VCC detection threshold for discharge enable */ - ch_raw_write16(BD9995X_CMD_VBUS_TH_SET, BD9995X_VBUS_DISCHARGE_TH, - BD9995X_EXTENDED_COMMAND); - ch_raw_write16(BD9995X_CMD_VCC_TH_SET, BD9995X_VBUS_DISCHARGE_TH, - BD9995X_EXTENDED_COMMAND); -#endif - - /* Unlock debug regs */ - ch_raw_write16(BD9995X_CMD_PROTECT_SET, 0x3c, BD9995X_EXTENDED_COMMAND); - - /* Undocumented - reverse current threshold = -50mV */ - ch_raw_write16(0x14, 0x0202, BD9995X_DEBUG_COMMAND); - /* Undocumented - internal gain = 2x */ - ch_raw_write16(0x1a, 0x80, BD9995X_DEBUG_COMMAND); - - /* Re-lock debug regs */ - ch_raw_write16(BD9995X_CMD_PROTECT_SET, 0x0, BD9995X_EXTENDED_COMMAND); -} -DECLARE_HOOK(HOOK_INIT, bd9995x_init, HOOK_PRIO_INIT_EXTPOWER); - -int charger_post_init(void) -{ - return EC_SUCCESS; -} - -int charger_discharge_on_ac(int enable) -{ - int rv; - int reg; - - rv = ch_raw_read16(BD9995X_CMD_CHGOP_SET2, ®, - BD9995X_EXTENDED_COMMAND); - if (rv) - return rv; - - /* - * Suspend USB charging and DC/DC converter so that BATT_LEARN mode - * doesn't auto exit if VBAT < VSYSVAL_THL_SET and also it helps to - * discharge VBUS quickly when charging is not allowed and the AC - * is removed. - */ - if (enable) - reg |= BD9995X_CMD_CHGOP_SET2_BATT_LEARN | - BD9995X_CMD_CHGOP_SET2_USB_SUS; - else - reg &= ~(BD9995X_CMD_CHGOP_SET2_BATT_LEARN | - BD9995X_CMD_CHGOP_SET2_USB_SUS); - - return ch_raw_write16(BD9995X_CMD_CHGOP_SET2, reg, - BD9995X_EXTENDED_COMMAND); -} - -int charger_get_vbus_voltage(int port) -{ - uint8_t read_reg; - int voltage; - - read_reg = (port == BD9995X_CHARGE_PORT_VBUS) ? BD9995X_CMD_VBUS_VAL : - BD9995X_CMD_VCC_VAL; - - return ch_raw_read16(read_reg, &voltage, BD9995X_EXTENDED_COMMAND) ? - 0 : voltage; -} - -/*** Non-standard interface functions ***/ - -int bd9995x_is_vbus_provided(enum bd9995x_charge_port port) -{ - int reg; - - if (ch_raw_read16(BD9995X_CMD_VBUS_VCC_STATUS, ®, - BD9995X_EXTENDED_COMMAND)) - return 0; - - if (port == BD9995X_CHARGE_PORT_VBUS) - reg &= BD9995X_CMD_VBUS_VCC_STATUS_VBUS_DETECT; - else if (port == BD9995X_CHARGE_PORT_VCC) - reg &= BD9995X_CMD_VBUS_VCC_STATUS_VCC_DETECT; - else if (port == BD9995X_CHARGE_PORT_BOTH) { - /* Check VBUS on either port */ - reg &= (BD9995X_CMD_VBUS_VCC_STATUS_VCC_DETECT | - BD9995X_CMD_VBUS_VCC_STATUS_VBUS_DETECT); - } else - reg = 0; - - return !!reg; -} - -#ifdef CONFIG_BD9995X_DELAY_INPUT_PORT_SELECT -static int bd9995x_select_input_port_private(enum bd9995x_charge_port port, - int select) -#else -int bd9995x_select_input_port(enum bd9995x_charge_port port, int select) -#endif -{ - int rv; - int reg; - - mutex_lock(&bd9995x_vin_mutex); - rv = ch_raw_read16(BD9995X_CMD_VIN_CTRL_SET, ®, - BD9995X_EXTENDED_COMMAND); - if (rv) - goto select_input_port_exit; - - if (select) { - if (port == BD9995X_CHARGE_PORT_VBUS) { - reg |= BD9995X_CMD_VIN_CTRL_SET_VBUS_EN; - reg &= ~BD9995X_CMD_VIN_CTRL_SET_VCC_EN; - } else if (port == BD9995X_CHARGE_PORT_VCC) { - reg |= BD9995X_CMD_VIN_CTRL_SET_VCC_EN; - reg &= ~BD9995X_CMD_VIN_CTRL_SET_VBUS_EN; - } else if (port == BD9995X_CHARGE_PORT_BOTH) { - /* Enable both the ports for PG3 */ - reg |= BD9995X_CMD_VIN_CTRL_SET_VBUS_EN | - BD9995X_CMD_VIN_CTRL_SET_VCC_EN; - } else { - /* Invalid charge port */ - panic("Invalid charge port"); - } - } else { - if (port == BD9995X_CHARGE_PORT_VBUS) - reg &= ~BD9995X_CMD_VIN_CTRL_SET_VBUS_EN; - else if (port == BD9995X_CHARGE_PORT_VCC) - reg &= ~BD9995X_CMD_VIN_CTRL_SET_VCC_EN; - else if (port == BD9995X_CHARGE_PORT_BOTH) - reg &= ~(BD9995X_CMD_VIN_CTRL_SET_VBUS_EN | - BD9995X_CMD_VIN_CTRL_SET_VCC_EN); - else - panic("Invalid charge port"); - } - - rv = ch_raw_write16(BD9995X_CMD_VIN_CTRL_SET, reg, - BD9995X_EXTENDED_COMMAND); -select_input_port_exit: - mutex_unlock(&bd9995x_vin_mutex); - return rv; -} - -#ifdef CONFIG_BD9995X_DELAY_INPUT_PORT_SELECT -int bd9995x_select_input_port(enum bd9995x_charge_port port, int select) -{ - port_update = port; - select_update = select; - vbus_state = START; - select_input_port_update = 1; - task_wake(TASK_ID_USB_CHG); - - return EC_SUCCESS; -} - -static inline int bd9995x_vbus_test(int value, int limit) -{ - uint32_t hi_value = limit + VBUS_DELTA; - uint32_t lo_value = limit - VBUS_DELTA; - - return ((value > lo_value) && (value < hi_value)); -} - -static int bd9995x_vbus_debounce(enum bd9995x_charge_port port) -{ - int vbus_reg; - int voltage; - - vbus_reg = (port == BD9995X_CHARGE_PORT_VBUS) ? - BD9995X_CMD_VBUS_VAL : BD9995X_CMD_VCC_VAL; - if (ch_raw_read16(vbus_reg, &voltage, BD9995X_EXTENDED_COMMAND)) - voltage = 0; - - if (!bd9995x_vbus_test(voltage, vbus_voltage)) { - vbus_voltage = voltage; - debounce_time = get_time().val + VBUS_MSEC; - } else { - if (get_time().val >= debounce_time) - return 1; - } - - return 0; -} -#endif - - -#ifdef CONFIG_CHARGER_BATTERY_TSENSE -int bd9995x_get_battery_temp(int *temp_ptr) -{ - int rv; - - rv = ch_raw_read16(BD9995X_CMD_THERM_VAL, temp_ptr, - BD9995X_EXTENDED_COMMAND); - if (rv) - return rv; - - /* Degrees C = 200 - THERM_VAL, range is -55C-200C, 1C steps */ - *temp_ptr = 200 - *temp_ptr; - return EC_SUCCESS; -} -#endif - -void bd9995x_set_power_save_mode(int mode) -{ - ch_raw_write16(BD9995X_CMD_SMBREG, mode, BD9995X_EXTENDED_COMMAND); -} - -int bd9995x_get_battery_voltage(void) -{ - int vbat_val, rv; - - rv = ch_raw_read16(BD9995X_CMD_VBAT_VAL, &vbat_val, - BD9995X_EXTENDED_COMMAND); - - return rv ? 0 : vbat_val; -} - -#ifdef HAS_TASK_USB_CHG -int bd9995x_bc12_enable_charging(int port, int enable) -{ - int rv; - int reg; - int mask_val; - - /* - * For BC1.2, enable VBUS/VCC_BC_DISEN charging trigger by BC1.2 - * detection and disable SDP_CHG_TRIG, SDP_CHG_TRIG_EN. Vice versa - * for USB-C. - */ - rv = ch_raw_read16(BD9995X_CMD_CHGOP_SET1, ®, - BD9995X_EXTENDED_COMMAND); - if (rv) - return rv; - - mask_val = (BD9995X_CMD_CHGOP_SET1_SDP_CHG_TRIG_EN | - BD9995X_CMD_CHGOP_SET1_SDP_CHG_TRIG | - ((port == BD9995X_CHARGE_PORT_VBUS) ? - BD9995X_CMD_CHGOP_SET1_VBUS_BC_DISEN : - BD9995X_CMD_CHGOP_SET1_VCC_BC_DISEN)); - - if (enable) - reg &= ~mask_val; - else - reg |= mask_val; - - return ch_raw_write16(BD9995X_CMD_CHGOP_SET1, reg, - BD9995X_EXTENDED_COMMAND); -} - -void usb_charger_set_switches(int port, enum usb_switch setting) -{ - /* If switch is not changing then return */ - if (setting == usb_switch_state[port]) - return; - - if (setting != USB_SWITCH_RESTORE) - usb_switch_state[port] = setting; - - /* ensure we disable power saving when we are using DP/DN */ -#ifdef CONFIG_BD9995X_POWER_SAVE_MODE - bd9995x_set_power_save_mode( - (usb_switch_state[0] == USB_SWITCH_DISCONNECT && - usb_switch_state[1] == USB_SWITCH_DISCONNECT) - ? CONFIG_BD9995X_POWER_SAVE_MODE : BD9995X_PWR_SAVE_OFF); -#endif - - bd9995x_update_ucd_set_reg(port, BD9995X_CMD_UCD_SET_USB_SW, - usb_switch_state[port] == USB_SWITCH_CONNECT); -} - -void bd9995x_vbus_interrupt(enum gpio_signal signal) -{ - task_wake(TASK_ID_USB_CHG); -} - -void usb_charger_task(void *u) -{ - static int initialized; - int changed, port, interrupts; - int sleep_usec; - uint64_t bc12_det_mark[CONFIG_USB_PD_PORT_MAX_COUNT]; -#ifdef CONFIG_USB_PD_DISCHARGE - int vbus_reg, voltage; -#endif - -#ifdef CONFIG_BD9995X_DELAY_INPUT_PORT_SELECT - select_input_port_update = 0; - vbus_voltage = 0; -#endif - - for (port = 0; port < board_get_usb_pd_port_count(); port++) { - bc12_detected_type[port] = CHARGE_SUPPLIER_NONE; - bd9995x_enable_vbus_detect_interrupts(port, 1); - bc12_det_mark[port] = 0; - } - - while (1) { - sleep_usec = -1; - changed = 0; - for (port = 0; port < board_get_usb_pd_port_count(); port++) { - /* Get port interrupts */ - interrupts = bd9995x_get_interrupts(port); - if (interrupts & BD9995X_CMD_INT_VBUS_DET || - !initialized) { - /* - * Detect based on current state of VBUS. If - * VBUS is provided, then need to wait for - * bc12_type to be available. If VBUS is not - * provided, then disable wait for this port. - */ - bc12_det_mark[port] = usb_charger_process(port) - ? get_time().val + BC12_DETECT_US : 0; - changed = 1; - } -#ifdef CONFIG_USB_PD_DISCHARGE - if (interrupts & BD9995X_CMD_INT_VBUS_TH || - !initialized) { - /* Get VBUS voltage */ - vbus_reg = (port == BD9995X_CHARGE_PORT_VBUS) ? - BD9995X_CMD_VBUS_VAL : - BD9995X_CMD_VCC_VAL; - if (ch_raw_read16(vbus_reg, - &voltage, - BD9995X_EXTENDED_COMMAND)) - voltage = 0; - - /* Set discharge accordingly */ - pd_set_vbus_discharge(port, - voltage < BD9995X_VBUS_DISCHARGE_TH); - changed = 1; - } -#endif - if (bc12_det_mark[port] && (get_time().val > - bc12_det_mark[port])) { - /* - * bc12_type result should be available. If not - * available still, then function will return - * 1. Set up additional 100 msec wait. Note that - * if VBUS is no longer provided when this call - * happens the funciton will return 0. - */ - bc12_det_mark[port] = - bd9995x_bc12_check_type(port) ? - get_time().val + 100 * MSEC : 0; - /* Reset BC1.2 regs to skip auto-detection. */ - bd9995x_bc12_detect(port, 0); - } - - /* - * Determine if a wait for reading bc12_type needs to be - * scheduled. Use the scheduled wait for this port if - * it's less than the wait needed for a previous - * port. If previous port(s) don't need a wait, then - * sleep_usec will be -1. - */ - if (bc12_det_mark[port]) { - int bc12_wait_usec; - - bc12_wait_usec = bc12_det_mark[port] - - get_time().val; - if ((sleep_usec < 0) || - (sleep_usec > bc12_wait_usec)) - sleep_usec = bc12_wait_usec; - } - } - - initialized = 1; -#ifdef CONFIG_BD9995X_DELAY_INPUT_PORT_SELECT -/* - * When a charge port is selected and VBUS is 5V, the inrush current on some - * devices causes VBUS to droop, which could signal a sink disconnection. - * - * To mitigate the problem, charge port selection is delayed until VBUS - * is stable or one second has passed. Hopefully PD has negotiated a VBUS - * voltage of at least 9V before the one second timeout. - */ - if (select_input_port_update) { - sleep_usec = VBUS_CHECK_MSEC; - changed = 0; - - switch (vbus_state) { - case START: - vbus_timeout = get_time().val + STABLE_TIMEOUT; - vbus_state = STABLE; - break; - case STABLE: - if (get_time().val > vbus_timeout) { - vbus_state = DEBOUNCE; - vbus_timeout = get_time().val + - DEBOUNCE_TIMEOUT; - } - break; - case DEBOUNCE: - if (bd9995x_vbus_debounce(port_update) || - get_time().val > vbus_timeout) { - select_input_port_update = 0; - bd9995x_select_input_port_private( - port_update, select_update); - } - break; - } - } -#endif - - /* - * Re-read interrupt registers immediately if we got an - * interrupt. We're dealing with multiple independent - * interrupt sources and the interrupt pin may have - * never deasserted if both sources were not in clear - * state simultaneously. - */ - if (!changed) - task_wait_event(sleep_usec); - } -} -#endif /* HAS_TASK_USB_CHG */ - - -/*** Console commands ***/ -#ifdef CONFIG_CMD_CHARGER_DUMP -static int read_bat(uint8_t cmd) -{ - int read = 0; - - ch_raw_read16(cmd, &read, BD9995X_BAT_CHG_COMMAND); - return read; -} - -static int read_ext(uint8_t cmd) -{ - int read = 0; - - ch_raw_read16(cmd, &read, BD9995X_EXTENDED_COMMAND); - return read; -} - -/* Dump all readable registers on bd9995x */ -static int console_bd9995x_dump_regs(int argc, char **argv) -{ - int i; - uint8_t regs[] = { 0x14, 0x15, 0x3c, 0x3d, 0x3e, 0x3f }; - - /* Battery group registers */ - for (i = 0; i < ARRAY_SIZE(regs); ++i) - ccprintf("BAT REG %4x: %4x\n", regs[i], read_bat(regs[i])); - - /* Extended group registers */ - for (i = 0; i < 0x7f; ++i) { - ccprintf("EXT REG %4x: %4x\n", i, read_ext(i)); - cflush(); - } - - return 0; -} -DECLARE_CONSOLE_COMMAND(charger_dump, console_bd9995x_dump_regs, - NULL, - "Dump all charger registers"); -#endif /* CONFIG_CMD_CHARGER_DUMP */ - -#ifdef CONFIG_CMD_CHARGER -static int console_command_bd9995x(int argc, char **argv) -{ - int rv, reg, data, val; - char rw, *e; - enum bd9995x_command cmd; - - if (argc < 4) - return EC_ERROR_PARAM_COUNT; - - rw = argv[1][0]; - if (rw == 'w' && argc < 5) - return EC_ERROR_PARAM_COUNT; - else if (rw != 'w' && rw != 'r') - return EC_ERROR_PARAM1; - - reg = strtoi(argv[2], &e, 16); - if (*e || reg < 0) - return EC_ERROR_PARAM2; - - cmd = strtoi(argv[3], &e, 0); - if (*e || cmd < 0) - return EC_ERROR_PARAM3; - - if (rw == 'r') - rv = ch_raw_read16(reg, &data, cmd); - else { - val = strtoi(argv[4], &e, 16); - if (*e || val < 0) - return EC_ERROR_PARAM4; - - rv = ch_raw_write16(reg, val, cmd); - if (rv == EC_SUCCESS) - rv = ch_raw_read16(reg, &data, cmd); - } - - if (rv == EC_SUCCESS) - CPRINTS("register 0x%x [%d] = 0x%x [%d]", reg, reg, data, data); - - return rv; -} -DECLARE_CONSOLE_COMMAND(bd9995x, console_command_bd9995x, - "bd9995x <r/w> <reg_hex> <cmd_type> | <val_hex>", - "Read or write a charger register"); -#endif /* CONFIG_CMD_CHARGER */ - -#ifdef CONFIG_CHARGER_PSYS_READ -static int bd9995x_psys_charger_adc(void) -{ - int i; - int reg; - uint64_t ipmon = 0; - - for (i = 0; i < BD9995X_PMON_IOUT_ADC_READ_COUNT; i++) { - if (ch_raw_read16(BD9995X_CMD_PMON_DACIN_VAL, ®, - BD9995X_EXTENDED_COMMAND)) - return 0; - - /* Conversion Interval is 200us */ - usleep(200); - ipmon += reg; - } - - /* - * Calculate power in mW - * PSYS = VACP×IACP+VBAT×IBAT = IPMON / GPMON - */ - return (int) ((ipmon * 1000) / (BIT(BD9995X_PSYS_GAIN_SELECT) * - BD9995X_PMON_IOUT_ADC_READ_COUNT)); -} - -static int bd9995x_enable_psys(void) -{ - int rv; - int reg; - - rv = ch_raw_read16(BD9995X_CMD_PMON_IOUT_CTRL_SET, ®, - BD9995X_EXTENDED_COMMAND); - if (rv) - return rv; - - /* Enable PSYS & Select PSYS Gain */ - reg &= ~BD9995X_CMD_PMON_IOUT_CTRL_SET_PMON_GAIN_SET_MASK; - reg |= (BD9995X_CMD_PMON_IOUT_CTRL_SET_PMON_INSEL | - BD9995X_CMD_PMON_IOUT_CTRL_SET_PMON_OUT_EN | - BD9995X_PSYS_GAIN_SELECT); - - return ch_raw_write16(BD9995X_CMD_PMON_IOUT_CTRL_SET, reg, - BD9995X_EXTENDED_COMMAND); -} - -/** - * Get system power. - * - * TODO(b:71520677): Implement charger_get_system_power, disable psys readout - * when not needed (the code below leaves it enabled after the first access), - * update "psys" console command to use charger_get_system_power and move it - * to some common code. - */ -static int console_command_psys(int argc, char **argv) -{ - int rv; - - rv = bd9995x_enable_psys(); - if (rv) - return rv; - - CPRINTS("PSYS from chg_adc: %d mW", - bd9995x_psys_charger_adc()); - - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(psys, console_command_psys, - NULL, - "Get the system power in mW"); -#endif /* CONFIG_CHARGER_PSYS_READ */ - -#ifdef CONFIG_CMD_CHARGER_ADC_AMON_BMON -static int bd9995x_amon_bmon_chg_adc(void) -{ - int i; - int reg; - int iout = 0; - - for (i = 0; i < BD9995X_PMON_IOUT_ADC_READ_COUNT; i++) { - ch_raw_read16(BD9995X_CMD_IOUT_DACIN_VAL, ®, - BD9995X_EXTENDED_COMMAND); - iout += reg; - - /* Conversion Interval is 200us */ - usleep(200); - } - - /* - * Discharge current in mA - * IDCHG = iout * GIDCHG - * IADP = iout * GIADP - * - * VIDCHG = GIDCHG * (VSRN- VSRP) = GIDCHG * IDCHG / IDCHG_RES - * VIADP = GIADP * (VACP- VACN) = GIADP * IADP / IADP_RES - */ - return (iout * (5 << BD9995X_IOUT_GAIN_SELECT)) / - (10 * BD9995X_PMON_IOUT_ADC_READ_COUNT); -} - -static int bd9995x_amon_bmon(int amon_bmon) -{ - int rv; - int reg; - int imon; - int sns_res; - - rv = ch_raw_read16(BD9995X_CMD_PMON_IOUT_CTRL_SET, ®, - BD9995X_EXTENDED_COMMAND); - if (rv) - return rv; - - /* Enable monitor */ - reg &= ~BD9995X_CMD_PMON_IOUT_CTRL_SET_IOUT_GAIN_SET_MASK; - reg |= (BD9995X_CMD_PMON_IOUT_CTRL_SET_IMON_INSEL | - BD9995X_CMD_PMON_IOUT_CTRL_SET_IOUT_OUT_EN | - (BD9995X_IOUT_GAIN_SELECT << 4)); - - if (amon_bmon) { - reg |= BD9995X_CMD_PMON_IOUT_CTRL_SET_IOUT_SOURCE_SEL; - sns_res = CONFIG_CHARGER_SENSE_RESISTOR_AC; - } else { - reg &= ~BD9995X_CMD_PMON_IOUT_CTRL_SET_IOUT_SOURCE_SEL; - sns_res = CONFIG_CHARGER_SENSE_RESISTOR; - } - - rv = ch_raw_write16(BD9995X_CMD_PMON_IOUT_CTRL_SET, reg, - BD9995X_EXTENDED_COMMAND); - if (rv) - return rv; - - imon = bd9995x_amon_bmon_chg_adc(); - - CPRINTS("%cMON from chg_adc: %d uV, %d mA]", - amon_bmon ? 'A' : 'B', - imon * sns_res, - imon); - - return EC_SUCCESS; -} - -/** - * Get charger AMON and BMON current. - */ -static int console_command_amon_bmon(int argc, char **argv) -{ - int rv = EC_ERROR_PARAM1; - - /* Switch to AMON */ - if (argc == 1 || (argc >= 2 && argv[1][0] == 'a')) - rv = bd9995x_amon_bmon(1); - - /* Switch to BMON */ - if (argc == 1 || (argc >= 2 && argv[1][0] == 'b')) - rv = bd9995x_amon_bmon(0); - - return rv; -} -DECLARE_CONSOLE_COMMAND(amonbmon, console_command_amon_bmon, - "amonbmon [a|b]", - "Get charger AMON/BMON voltage diff, current"); -#endif /* CONFIG_CMD_CHARGER_ADC_AMON_BMON */ - -#ifdef CONFIG_CMD_I2C_STRESS_TEST_CHARGER -static int bd9995x_i2c_read(const int reg, int *data) -{ - return ch_raw_read16(reg, data, BD9995X_EXTENDED_COMMAND); -} - -static int bd9995x_i2c_write(const int reg, int data) -{ - return ch_raw_write16(reg, data, BD9995X_EXTENDED_COMMAND); -} - -/* BD9995X_CMD_CHIP_ID register value may vary by chip. */ -struct i2c_stress_test_dev bd9995x_i2c_stress_test_dev = { - .reg_info = { - .read_reg = BD9995X_CMD_CHIP_ID, - .read_val = BD99956_CHIP_ID, - .write_reg = BD9995X_CMD_ITRICH_SET, - }, - .i2c_read_dev = &bd9995x_i2c_read, - .i2c_write_dev = &bd9995x_i2c_write, -}; -#endif /* CONFIG_CMD_I2C_STRESS_TEST_CHARGER */ diff --git a/driver/charger/bd9995x.h b/driver/charger/bd9995x.h deleted file mode 100644 index 491f4bdeac..0000000000 --- a/driver/charger/bd9995x.h +++ /dev/null @@ -1,364 +0,0 @@ -/* 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. - * - * ROHM BD9995X battery charger driver. - */ - -#ifndef __CROS_EC_BD9995X_H -#define __CROS_EC_BD9995X_H - -#define BD9995X_ADDR_FLAGS 0x09 -#define I2C_ADDR_CHARGER_FLAGS BD9995X_ADDR_FLAGS - -#define BD9995X_CHARGER_NAME "bd9995x" -#define BD99955_CHIP_ID 0x221 -#define BD99956_CHIP_ID 0x331 - -/* BD9995X commands to change the command code map */ -enum bd9995x_command { - BD9995X_BAT_CHG_COMMAND, - BD9995X_EXTENDED_COMMAND, - BD9995X_DEBUG_COMMAND, - BD9995X_INVALID_COMMAND -}; - -/* - * BD9995X has two external VBUS inputs (named VBUS and VCC) and two sets - * of registers / bits for control. This entire driver is written under the - * assumption that the physical VBUS port corresponds to PD port 0, and the - * physical VCC port corresponds to PD port 1. - */ -enum bd9995x_charge_port { - BD9995X_CHARGE_PORT_VBUS, - BD9995X_CHARGE_PORT_VCC, - BD9995X_CHARGE_PORT_BOTH, -}; - -/* Charger parameters */ -#define CHARGER_NAME BD9995X_CHARGER_NAME -#define CHARGE_V_MAX 19200 -#define CHARGE_V_MIN 3072 -#define CHARGE_V_STEP 16 -#define CHARGE_I_MAX 16320 -#define CHARGE_I_MIN 128 -#define CHARGE_I_OFF 0 -#define CHARGE_I_STEP 64 -#define INPUT_I_MAX 16352 -#define INPUT_I_MIN 512 -#define INPUT_I_STEP 32 - -/* Min. charge current w/ no battery to prevent collapse */ -#define BD9995X_NO_BATTERY_CHARGE_I_MIN 512 - -/* - * BC1.2 minimum voltage threshold. - * BC1.2 charging port output voltage range is 4.75V to 5.25V, - * BD9995X Anti-Collapse Threshold Voltage Accuracy is -100mV to +100mV, - * and Delta of 50mV. - */ -#define BD9995X_BC12_MIN_VOLTAGE 4600 - -/* Battery Charger Commands */ -#define BD9995X_CMD_CHG_CURRENT 0x14 -#define BD9995X_CMD_CHG_VOLTAGE 0x15 -#define BD9995X_CMD_IBUS_LIM_SET 0x3C -#define BD9995X_CMD_ICC_LIM_SET 0x3D -#define BD9995X_CMD_PROTECT_SET 0x3E -#define BD9995X_CMD_MAP_SET 0x3F - -/* Extended commands */ -#define BD9995X_CMD_CHGSTM_STATUS 0x00 -#define BD9995X_CMD_VBAT_VSYS_STATUS 0x01 -#define BD9995X_CMD_VBUS_VCC_STATUS 0x02 -#define BD9995X_CMD_VBUS_VCC_STATUS_VCC_DETECT BIT(8) -#define BD9995X_CMD_VBUS_VCC_STATUS_VBUS_DETECT BIT(0) - -#define BD9995X_CMD_CHGOP_STATUS 0x03 -#define BD9995X_CMD_CHGOP_STATUS_BATTEMP2 BIT(10) -#define BD9995X_CMD_CHGOP_STATUS_BATTEMP1 BIT(9) -#define BD9995X_CMD_CHGOP_STATUS_BATTEMP0 BIT(8) -#define BD9995X_BATTTEMP_MASK 0x700 -#define BD9995X_CMD_CHGOP_STATUS_BATTEMP_ROOMTEMP 0 -#define BD9995X_CMD_CHGOP_STATUS_BATTEMP_HOT1 1 -#define BD9995X_CMD_CHGOP_STATUS_BATTEMP_HOT2 2 -#define BD9995X_CMD_CHGOP_STATUS_BATTEMP_HOT3 3 -#define BD9995X_CMD_CHGOP_STATUS_BATTEMP_COLD1 4 -#define BD9995X_CMD_CHGOP_STATUS_BATTEMP_COLD2 5 -#define BD9995X_CMD_CHGOP_STATUS_BATTEMP_DISABLE 6 -#define BD9995X_CMD_CHGOP_STATUS_BATTEMP_BATOPEN 7 -#define BD9995X_CMD_CHGOP_STATUS_RBOOST_UV BIT(1) - -#define BD9995X_CMD_WDT_STATUS 0x04 -#define BD9995X_CMD_CUR_ILIM_VAL 0x05 -#define BD9995X_CMD_SEL_ILIM_VAL 0x06 -#define BD9995X_CMD_EXT_IBUS_LIM_SET 0x07 -#define BD9995X_CMD_EXT_ICC_LIM_SET 0x08 -#define BD9995X_CMD_IOTG_LIM_SET 0x09 -#define BD9995X_CMD_VIN_CTRL_SET 0x0A -#define BD9995X_CMD_VIN_CTRL_SET_VSYS_PRIORITY BIT(4) - -#define BD9995X_CMD_VIN_CTRL_SET_PP_BOTH_THRU BIT(11) -#define BD9995X_CMD_VIN_CTRL_SET_VBUS_PRIORITY BIT(7) -#define BD9995X_CMD_VIN_CTRL_SET_VBUS_EN BIT(6) -#define BD9995X_CMD_VIN_CTRL_SET_VCC_EN BIT(5) - -#define BD9995X_CMD_CHGOP_SET1 0x0B -#define BD9995X_CMD_CHGOP_SET1_DCP_2500_SEL BIT(15) -#define BD9995X_CMD_CHGOP_SET1_SDP_500_SEL BIT(14) -#define BD9995X_CMD_CHGOP_SET1_ILIM_AUTO_DISEN BIT(13) -#define BD9995X_CMD_CHGOP_SET1_VCC_BC_DISEN BIT(11) -#define BD9995X_CMD_CHGOP_SET1_VBUS_BC_DISEN BIT(10) -#define BD9995X_CMD_CHGOP_SET1_SDP_CHG_TRIG_EN BIT(9) -#define BD9995X_CMD_CHGOP_SET1_SDP_CHG_TRIG BIT(8) - -#define BD9995X_CMD_CHGOP_SET2 0x0C -#define BD9995X_CMD_CHGOP_SET2_BATT_LEARN BIT(8) -#define BD9995X_CMD_CHGOP_SET2_CHG_EN BIT(7) -#define BD9995X_CMD_CHGOP_SET2_USB_SUS BIT(6) -#define BD9995X_CMD_CHGOP_SET2_DCDC_CLK_SEL (3 << 2) -#define BD9995X_CMD_CHGOP_SET2_DCDC_CLK_SEL_600 (0 << 2) -#define BD9995X_CMD_CHGOP_SET2_DCDC_CLK_SEL_857 BIT(2) -#define BD9995X_CMD_CHGOP_SET2_DCDC_CLK_SEL_1000 (2 << 2) -#define BD9995X_CMD_CHGOP_SET2_DCDC_CLK_SEL_1200 (3 << 2) - -#define BD9995X_CMD_VBUSCLPS_TH_SET 0x0D -#define BD9995X_CMD_VCCCLPS_TH_SET 0x0E -#define BD9995X_CMD_CHGWDT_SET 0x0F -#define BD9995X_CMD_BATTWDT_SET 0x10 -#define BD9995X_CMD_VSYSREG_SET 0x11 -#define BD9995X_CMD_VSYSVAL_THH_SET 0x12 -#define BD9995X_CMD_VSYSVAL_THL_SET 0x13 -#define BD9995X_CMD_ITRICH_SET 0x14 - -#define BD9995X_CMD_IPRECH_SET 0x15 -#define BD9995X_IPRECH_MAX 1024 - -#define BD9995X_CMD_ICHG_SET 0x16 -#define BD9995X_CMD_ITERM_SET 0x17 -#define BD9995X_CMD_VPRECHG_TH_SET 0x18 -#define BD9995X_CMD_VRBOOST_SET 0x19 -#define BD9995X_CMD_VFASTCHG_REG_SET1 0x1A -#define BD9995X_CMD_VFASTCHG_REG_SET2 0x1B -#define BD9995X_CMD_VFASTCHG_REG_SET3 0x1C -#define BD9995X_CMD_VRECHG_SET 0x1D -#define BD9995X_CMD_VBATOVP_SET 0x1E -#define BD9995X_CMD_IBATSHORT_SET 0x1F -#define BD9995X_CMD_PROCHOT_CTRL_SET 0x20 -#define BD9995X_CMD_PROCHOT_CTRL_SET_PROCHOT_EN4 BIT(4) -#define BD9995X_CMD_PROCHOT_CTRL_SET_PROCHOT_EN3 BIT(3) -#define BD9995X_CMD_PROCHOT_CTRL_SET_PROCHOT_EN2 BIT(2) -#define BD9995X_CMD_PROCHOT_CTRL_SET_PROCHOT_EN1 BIT(1) -#define BD9995X_CMD_PROCHOT_CTRL_SET_PROCHOT_EN0 BIT(0) - -#define BD9995X_CMD_PROCHOT_ICRIT_SET 0x21 -#define BD9995X_CMD_PROCHOT_INORM_SET 0x22 -#define BD9995X_CMD_PROCHOT_IDCHG_SET 0x23 -#define BD9995X_CMD_PROCHOT_VSYS_SET 0x24 -#define BD9995X_CMD_PMON_IOUT_CTRL_SET 0x25 -#define BD9995X_CMD_PMON_IOUT_CTRL_SET_IMON_INSEL BIT(9) -#define BD9995X_CMD_PMON_IOUT_CTRL_SET_PMON_INSEL BIT(8) -#define BD9995X_CMD_PMON_IOUT_CTRL_SET_IOUT_OUT_EN BIT(7) -#define BD9995X_CMD_PMON_IOUT_CTRL_SET_IOUT_SOURCE_SEL BIT(6) -#define BD9995X_CMD_PMON_IOUT_CTRL_SET_IOUT_GAIN_SET_MASK 0x30 -#define BD9995X_CMD_PMON_IOUT_CTRL_SET_IOUT_GAIN_SET_40V 0x03 -#define BD9995X_CMD_PMON_IOUT_CTRL_SET_IOUT_GAIN_SET_20V 0x02 -#define BD9995X_CMD_PMON_IOUT_CTRL_SET_IOUT_GAIN_SET_10V 0x01 -#define BD9995X_CMD_PMON_IOUT_CTRL_SET_IOUT_GAIN_SET_05V 0x00 -#define BD9995X_CMD_PMON_IOUT_CTRL_SET_PMON_OUT_EN BIT(3) -#define BD9995X_CMD_PMON_IOUT_CTRL_SET_PMON_GAIN_SET_MASK 0x07 -#define BD9995X_CMD_PMON_IOUT_CTRL_SET_PMON_GAIN_SET_64UAW 0x06 -#define BD9995X_CMD_PMON_IOUT_CTRL_SET_PMON_GAIN_SET_32UAW 0x05 -#define BD9995X_CMD_PMON_IOUT_CTRL_SET_PMON_GAIN_SET_16UAW 0x04 -#define BD9995X_CMD_PMON_IOUT_CTRL_SET_PMON_GAIN_SET_08UAW 0x03 -#define BD9995X_CMD_PMON_IOUT_CTRL_SET_PMON_GAIN_SET_04UAW 0x02 -#define BD9995X_CMD_PMON_IOUT_CTRL_SET_PMON_GAIN_SET_02UAW 0x01 -#define BD9995X_CMD_PMON_IOUT_CTRL_SET_PMON_GAIN_SET_01UAW 0x00 -#define BD9995X_PMON_IOUT_ADC_READ_COUNT 128 - -#define BD9995X_CMD_PMON_DACIN_VAL 0x26 -#define BD9995X_CMD_IOUT_DACIN_VAL 0x27 -#define BD9995X_CMD_VCC_UCD_SET 0x28 -/* Bits for both VCC_UCD_SET and VBUS_UCD_SET regs */ -/* Retry BC1.2 detection on set */ -#define BD9995X_CMD_UCD_SET_BCSRETRY BIT(12) -/* Enable BC1.2 detection, will automatically occur on VBUS detect */ -#define BD9995X_CMD_UCD_SET_USBDETEN BIT(7) -/* USB switch state auto-control */ -#define BD9995X_CMD_UCD_SET_USB_SW_EN BIT(1) -/* USB switch state, 1 = ON, only meaningful when USB_SW_EN = 0 */ -#define BD9995X_CMD_UCD_SET_USB_SW BIT(0) - -#define BD9995X_CMD_VCC_UCD_STATUS 0x29 -/* Bits for both VCC_UCD_STATUS and VBUS_UCD_STATUS regs */ -#define BD9995X_CMD_UCD_STATUS_DCDFAIL BIT(15) -#define BD9995X_CMD_UCD_STATUS_CHGPORT1 BIT(13) -#define BD9995X_CMD_UCD_STATUS_CHGPORT0 BIT(12) -#define BD9995X_CMD_UCD_STATUS_PUPDET BIT(11) -#define BD9995X_CMD_UCD_STATUS_CHGDET BIT(6) -#define BD9995X_TYPE_MASK (BD9995X_CMD_UCD_STATUS_DCDFAIL | \ - BD9995X_CMD_UCD_STATUS_CHGPORT1 | \ - BD9995X_CMD_UCD_STATUS_CHGPORT0 | \ - BD9995X_CMD_UCD_STATUS_PUPDET | \ - BD9995X_CMD_UCD_STATUS_CHGDET) - -/* BC1.2 chargers */ -#define BD9995X_TYPE_CDP (BD9995X_CMD_UCD_STATUS_CHGPORT1 | \ - BD9995X_CMD_UCD_STATUS_CHGDET) -#define BD9995X_TYPE_DCP (BD9995X_CMD_UCD_STATUS_CHGPORT1 | \ - BD9995X_CMD_UCD_STATUS_CHGPORT0 | \ - BD9995X_CMD_UCD_STATUS_CHGDET) -#define BD9995X_TYPE_SDP (BD9995X_CMD_UCD_STATUS_CHGPORT0) -/* non-standard BC1.2 chargers */ -#define BD9995X_TYPE_OTHER (BD9995X_CMD_UCD_STATUS_DCDFAIL | \ - BD9995X_CMD_UCD_STATUS_CHGPORT1 | \ - BD9995X_CMD_UCD_STATUS_CHGPORT0 | \ - BD9995X_CMD_UCD_STATUS_CHGDET) -#define BD9995X_TYPE_PUP_PORT (BD9995X_CMD_UCD_STATUS_DCDFAIL | \ - BD9995X_CMD_UCD_STATUS_CHGPORT0 | \ - BD9995X_CMD_UCD_STATUS_PUPDET) -/* Open ports */ -#define BD9995X_TYPE_OPEN_PORT (BD9995X_CMD_UCD_STATUS_DCDFAIL | \ - BD9995X_CMD_UCD_STATUS_CHGPORT0) -#define BD9995X_TYPE_VBUS_OPEN 0 - -#define BD9995X_CMD_VCC_IDD_STATUS 0x2A -#define BD9995X_CMD_VCC_UCD_FCTRL_SET 0x2B -#define BD9995X_CMD_VCC_UCD_FCTRL_EN 0x2C -#define BD9995X_CMD_VBUS_UCD_SET 0x30 -#define BD9995X_CMD_VBUS_UCD_STATUS 0x31 -#define BD9995X_CMD_VBUS_IDD_STATUS 0x32 -#define BD9995X_CMD_VBUS_UCD_FCTRL_SET 0x33 -#define BD9995X_CMD_VBUS_UCD_FCTRL_EN 0x34 -#define BD9995X_CMD_CHIP_ID 0x38 -#define BD9995X_CMD_CHIP_REV 0x39 -#define BD9995X_CMD_IC_SET1 0x3A -#define BD9995X_CMD_IC_SET2 0x3B -#define BD9995X_CMD_SYSTEM_STATUS 0x3C -#define BD9995X_CMD_SYSTEM_STATUS_OTPLD_STATE BIT(1) -#define BD9995X_CMD_SYSTEM_STATUS_ALLRST_STATE BIT(0) - -#define BD9995X_CMD_SYSTEM_CTRL_SET 0x3D -#define BD9995X_CMD_SYSTEM_CTRL_SET_OTPLD BIT(1) -#define BD9995X_CMD_SYSTEM_CTRL_SET_ALLRST BIT(0) - -#define BD9995X_CMD_EXT_PROTECT_SET 0x3E -#define BD9995X_CMD_EXT_MAP_SET 0x3F -#define BD9995X_CMD_VM_CTRL_SET 0x40 -#define BD9995X_CMD_VM_CTRL_SET_EXTIADPEN BIT(9) -#define BD9995X_CMD_THERM_WINDOW_SET1 0x41 -#define BD9995X_CMD_THERM_WINDOW_SET2 0x42 -#define BD9995X_CMD_THERM_WINDOW_SET3 0x43 -#define BD9995X_CMD_THERM_WINDOW_SET4 0x44 -#define BD9995X_CMD_THERM_WINDOW_SET5 0x45 -#define BD9995X_CMD_IBATP_TH_SET 0x46 -#define BD9995X_CMD_IBATM_TH_SET 0x47 -#define BD9995X_CMD_VBAT_TH_SET 0x48 -#define BD9995X_CMD_THERM_TH_SET 0x49 -#define BD9995X_CMD_IACP_TH_SET 0x4A -#define BD9995X_CMD_VACP_TH_SET 0x4B - -/* Enable discharge when VBUS falls below BD9995X_VBUS_DISCHARGE_TH */ -#define BD9995X_VBUS_DISCHARGE_TH 3900 -#define BD9995X_CMD_VBUS_TH_SET 0x4C -#define BD9995X_CMD_VCC_TH_SET 0x4D - -#define BD9995X_CMD_VSYS_TH_SET 0x4E -#define BD9995X_CMD_EXTIADP_TH_SET 0x4F -#define BD9995X_CMD_IBATP_VAL 0x50 -#define BD9995X_CMD_IBATP_AVE_VAL 0x51 -#define BD9995X_CMD_IBATM_VAL 0x52 -#define BD9995X_CMD_IBATM_AVE_VAL 0x53 -#define BD9995X_CMD_VBAT_VAL 0x54 -#define BD9995X_CMD_VBAT_AVE_VAL 0x55 -#define BD9995X_CMD_THERM_VAL 0x56 -#define BD9995X_CMD_VTH_VAL 0x57 -#define BD9995X_CMD_IACP_VAL 0x58 -#define BD9995X_CMD_IACP_AVE_VAL 0x59 -#define BD9995X_CMD_VACP_VAL 0x5A -#define BD9995X_CMD_VACP_AVE_VAL 0x5B -#define BD9995X_CMD_VBUS_VAL 0x5C -#define BD9995X_CMD_VBUS_AVE_VAL 0x5D -#define BD9995X_CMD_VCC_VAL 0x5E -#define BD9995X_CMD_VCC_AVE_VAL 0x5F -#define BD9995X_CMD_VSYS_VAL 0x60 -#define BD9995X_CMD_VSYS_AVE_VAL 0x61 -#define BD9995X_CMD_EXTIADP_VAL 0x62 -#define BD9995X_CMD_EXTIADP_AVE_VAL 0x63 -#define BD9995X_CMD_VACPCLPS_TH_SET 0x64 -#define BD9995X_CMD_INT0_SET 0x68 -#define BD9995X_CMD_INT0_SET_INT2_EN BIT(2) -#define BD9995X_CMD_INT0_SET_INT1_EN BIT(1) -#define BD9995X_CMD_INT0_SET_INT0_EN BIT(0) - -#define BD9995X_CMD_INT1_SET 0x69 -/* Bits for both INT1 & INT2 reg */ -#define BD9995X_CMD_INT_SET_TH_DET BIT(9) -#define BD9995X_CMD_INT_SET_TH_RES BIT(8) -#define BD9995X_CMD_INT_SET_DET BIT(1) -#define BD9995X_CMD_INT_SET_RES BIT(0) -#define BD9995X_CMD_INT_VBUS_DET (BD9995X_CMD_INT_SET_RES | \ - BD9995X_CMD_INT_SET_DET) -#define BD9995X_CMD_INT_VBUS_TH (BD9995X_CMD_INT_SET_TH_RES | \ - BD9995X_CMD_INT_SET_TH_DET) - -#define BD9995X_CMD_INT2_SET 0x6A -#define BD9995X_CMD_INT3_SET 0x6B -#define BD9995X_CMD_INT4_SET 0x6C -#define BD9995X_CMD_INT5_SET 0x6D -#define BD9995X_CMD_INT6_SET 0x6E -#define BD9995X_CMD_INT7_SET 0x6F -#define BD9995X_CMD_INT0_STATUS 0x70 -#define BD9995X_CMD_INT1_STATUS 0x71 -/* Bits for both INT1_STATUS & INT2_STATUS reg */ -#define BD9995X_CMD_INT_STATUS_DET BIT(1) -#define BD9995X_CMD_INT_STATUS_RES BIT(0) - -#define BD9995X_CMD_INT2_STATUS 0x72 -#define BD9995X_CMD_INT3_STATUS 0x73 -#define BD9995X_CMD_INT4_STATUS 0x74 -#define BD9995X_CMD_INT5_STATUS 0x75 -#define BD9995X_CMD_INT6_STATUS 0x76 -#define BD9995X_CMD_INT7_STATUS 0x77 -#define BD9995X_CMD_REG0 0x78 -#define BD9995X_CMD_REG1 0x79 -#define BD9995X_CMD_OTPREG0 0x7A -#define BD9995X_CMD_OTPREG1 0x7B -#define BD9995X_CMD_SMBREG 0x7C -/* Normal functionality - power save mode disabled. */ -#define BD9995X_PWR_SAVE_OFF 0 -/* BGATE ON w/ PROCHOT# monitored only system voltage. */ -#define BD9995X_PWR_SAVE_LOW 0x1 -/* BGATE ON w/ PROCHOT# monitored only system voltage every 1ms. */ -#define BD9995X_PWR_SAVE_MED 0x2 -/* BGATE ON w/o PROCHOT# monitoring. */ -#define BD9995X_PWR_SAVE_HIGH 0x5 -/* BGATE OFF */ -#define BD9995X_PWR_SAVE_MAX 0x6 -#define BD9995X_CMD_DEBUG_MODE_SET 0x7F - -/* - * Non-standard interface functions - bd9995x integrates additional - * functionality not part of the standard charger interface. - */ - -/* Is VBUS provided or external power present */ -int bd9995x_is_vbus_provided(enum bd9995x_charge_port port); -/* Select or deselect input port from {VCC, VBUS, VCC&VBUS}. */ -int bd9995x_select_input_port(enum bd9995x_charge_port port, int select); -/* Enable/Disable charging triggered by BC1.2 */ -int bd9995x_bc12_enable_charging(int port, int enable); -/* Interrupt handler for USB charger VBUS */ -void bd9995x_vbus_interrupt(enum gpio_signal signal); -/* Read temperature measurement value (in Celsius) */ -int bd9995x_get_battery_temp(int *temp_ptr); -/* Set power save mode */ -void bd9995x_set_power_save_mode(int mode); -/* Get Battery Voltage Measurement Value */ -int bd9995x_get_battery_voltage(void); - -#ifdef CONFIG_CMD_I2C_STRESS_TEST_CHARGER -extern struct i2c_stress_test_dev bd9995x_i2c_stress_test_dev; -#endif - -#endif /* __CROS_EC_BD9995X_H */ diff --git a/driver/charger/bq24192.c b/driver/charger/bq24192.c deleted file mode 100644 index 3345bab093..0000000000 --- a/driver/charger/bq24192.c +++ /dev/null @@ -1,277 +0,0 @@ -/* Copyright 2012 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. - * - * TI bq24192 battery charger driver. - */ - -#include "bq24192.h" -#include "charger.h" -#include "common.h" -#include "console.h" -#include "gpio.h" -#include "hooks.h" -#include "i2c.h" -#include "printf.h" -#include "util.h" - -/* Console output macros */ -#define CPUTS(outstr) cputs(CC_CHARGER, outstr) -#define CPRINTF(format, args...) cprintf(CC_CHARGER, format, ## args) - -/* Charger information */ -static const struct charger_info bq24192_charger_info = { - .name = "bq24192", - .voltage_max = 4400, - .voltage_min = 3504, - .voltage_step = 16, - .current_max = 4544, - .current_min = 512, - .current_step = 64, - .input_current_max = 3000, - .input_current_min = 100, - .input_current_step = -1, -}; - -static const int input_current_steps[] = { - 100, 150, 500, 900, 1200, 1500, 2000, 3000}; - -static int bq24192_read(int reg, int *value) -{ - return i2c_read8(I2C_PORT_CHARGER, BQ24192_ADDR, reg, value); -} - -static int bq24192_write(int reg, int value) -{ - return i2c_write8(I2C_PORT_CHARGER, BQ24192_ADDR, reg, value); -} - -static int bq24192_watchdog_reset(void) -{ - int rv, val; - - rv = bq24192_read(BQ24192_REG_POWER_ON_CFG, &val); - if (rv) - return rv; - val |= BIT(6); - return bq24192_write(BQ24192_REG_POWER_ON_CFG, val) || - bq24192_write(BQ24192_REG_POWER_ON_CFG, val); -} - -static int bq24192_set_terminate_current(int current) -{ - int reg_val, rv; - int val = (current - 128) / 128; - - rv = bq24192_read(BQ24192_REG_PRE_CHG_CURRENT, ®_val); - if (rv) - return rv; - reg_val = (reg_val & ~0xf) | (val & 0xf); - return bq24192_write(BQ24192_REG_PRE_CHG_CURRENT, reg_val); -} - -#ifdef CONFIG_CHARGER_OTG -int charger_enable_otg_power(int enabled) -{ - int val, rv; - - gpio_set_level(GPIO_BCHGR_OTG, enabled); - rv = bq24192_read(BQ24192_REG_POWER_ON_CFG, &val); - if (rv) - return rv; - val = (val & ~0x30) | (enabled ? 0x20 : 0x10); - return bq24192_write(BQ24192_REG_POWER_ON_CFG, val); -} -#endif - -int charger_set_input_current(int input_current) -{ - int i, value, rv; - - for (i = 1; i < ARRAY_SIZE(input_current_steps); ++i) - if (input_current_steps[i] > input_current) { - --i; - break; - } - if (i == ARRAY_SIZE(input_current_steps)) - --i; - - rv = bq24192_read(BQ24192_REG_INPUT_CTRL, &value); - if (rv) - return rv; - value = value & ~(0x7); - value |= (i & 0x7); - return bq24192_write(BQ24192_REG_INPUT_CTRL, value); -} - -int charger_get_input_current(int *input_current) -{ - int rv, value; - - rv = bq24192_read(BQ24192_REG_INPUT_CTRL, &value); - if (rv) - return rv; - *input_current = input_current_steps[value & 0x7]; - return EC_SUCCESS; -} - -int charger_manufacturer_id(int *id) -{ - return EC_ERROR_UNIMPLEMENTED; -} - -int charger_device_id(int *id) -{ - return bq24192_read(BQ24192_REG_ID, id); -} - -int charger_get_option(int *option) -{ - return EC_ERROR_UNIMPLEMENTED; -} - -int charger_set_option(int option) -{ - return EC_ERROR_UNIMPLEMENTED; -} - -const struct charger_info *charger_get_info(void) -{ - return &bq24192_charger_info; -} - -int charger_get_status(int *status) -{ - return EC_ERROR_UNIMPLEMENTED; -} - -int charger_set_mode(int mode) -{ - return EC_ERROR_UNIMPLEMENTED; -} - -int charger_get_current(int *current) -{ - int rv, val; - const struct charger_info * const info = charger_get_info(); - - rv = bq24192_read(BQ24192_REG_CHG_CURRENT, &val); - if (rv) - return rv; - val = (val >> 2) & 0x3f; - *current = val * info->current_step + info->current_min; - return EC_SUCCESS; -} - -int charger_set_current(int current) -{ - int rv, val; - const struct charger_info * const info = charger_get_info(); - - current = charger_closest_current(current); - rv = bq24192_read(BQ24192_REG_CHG_CURRENT, &val); - if (rv) - return rv; - val = val & 0x3; - val |= ((current - info->current_min) / info->current_step) << 2; - return bq24192_write(BQ24192_REG_CHG_CURRENT, val); -} - -int charger_get_voltage(int *voltage) -{ - int rv, val; - const struct charger_info * const info = charger_get_info(); - - rv = bq24192_read(BQ24192_REG_CHG_VOLTAGE, &val); - if (rv) - return rv; - val = (val >> 2) & 0x3f; - *voltage = val * info->voltage_step + info->voltage_min; - return EC_SUCCESS; -} - -int charger_set_voltage(int voltage) -{ - int rv, val; - const struct charger_info * const info = charger_get_info(); - - rv = bq24192_read(BQ24192_REG_CHG_VOLTAGE, &val); - if (rv) - return rv; - val = val & 0x3; - val |= ((voltage - info->voltage_min) / info->voltage_step) << 2; - return bq24192_write(BQ24192_REG_CHG_VOLTAGE, val); -} - -/* Charging power state initialization */ -int charger_post_init(void) -{ - /* Input current controlled by extpower module. Do nothing here. */ - return EC_SUCCESS; -} - - -/*****************************************************************************/ -/* Hooks */ - -static void bq24192_init(void) -{ - int val; - - if (charger_device_id(&val) || val != BQ24192_DEVICE_ID) { - CPRINTF("BQ24192 incorrent ID: 0x%02x\n", val); - return; - } - - /* - * Disable I2C watchdog timer. - * - * TODO(crosbug.com/p/22238): Re-enable watchdog timer and kick it - * periodically in charger task. - */ - if (bq24192_read(BQ24192_REG_CHG_TERM_TMR, &val)) - return; - - val &= ~0x30; - - if (bq24192_write(BQ24192_REG_CHG_TERM_TMR, val)) - return; - - if (bq24192_set_terminate_current(128)) - return; - - if (bq24192_watchdog_reset()) - return; - - CPRINTF("BQ24192 initialized\n"); -} -DECLARE_HOOK(HOOK_INIT, bq24192_init, HOOK_PRIO_LAST); - -/*****************************************************************************/ -/* Console commands */ -#ifdef CONFIG_CMD_CHARGER -static int command_bq24192(int argc, char **argv) -{ - int i; - int value; - int rv; - - ccprintf("REG:"); - for (i = 0; i <= 0xa; ++i) - ccprintf(" %02x", i); - ccprintf("\n"); - - ccprintf("VAL:"); - for (i = 0; i <= 0xa; ++i) { - rv = bq24192_read(i, &value); - if (rv) - return rv; - ccprintf(" %02x", value); - } - ccprintf("\n"); - - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(bq24192, command_bq24192, - NULL, NULL); -#endif diff --git a/driver/charger/bq24192.h b/driver/charger/bq24192.h deleted file mode 100644 index b82fe93a02..0000000000 --- a/driver/charger/bq24192.h +++ /dev/null @@ -1,28 +0,0 @@ -/* Copyright 2013 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. - * - * TI bq24192 battery charger driver. - */ - -#ifndef __CROS_EC_BQ24192_H -#define __CROS_EC_BQ24192_H - -#define BQ24192_ADDR_FLAGS 0x6b - -/* Registers */ -#define BQ24192_REG_INPUT_CTRL 0x0 -#define BQ24192_REG_POWER_ON_CFG 0x1 -#define BQ24192_REG_CHG_CURRENT 0x2 -#define BQ24192_REG_PRE_CHG_CURRENT 0x3 -#define BQ24192_REG_CHG_VOLTAGE 0x4 -#define BQ24192_REG_CHG_TERM_TMR 0x5 -#define BQ24192_REG_IR_COMP 0x6 -#define BQ24192_REG_MISC_OP 0x7 -#define BQ24192_REG_STATUS 0x8 -#define BQ24192_REG_FAULT 0x9 -#define BQ24192_REG_ID 0xa - -#define BQ24192_DEVICE_ID 0x2b - -#endif /* __CROS_EC_BQ24192_H */ diff --git a/driver/charger/bq24707a.c b/driver/charger/bq24707a.c deleted file mode 100644 index 53e3f5b531..0000000000 --- a/driver/charger/bq24707a.c +++ /dev/null @@ -1,178 +0,0 @@ -/* Copyright 2012 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. - * - * TI bq24707A battery charger driver. - */ - -#include "battery_smart.h" -#include "bq24707a.h" -#include "charger.h" -#include "console.h" -#include "common.h" -#include "i2c.h" -#include "util.h" - -/* Sense resistor configurations and macros */ -#define DEFAULT_SENSE_RESISTOR 10 -#define R_SNS CONFIG_CHARGER_SENSE_RESISTOR -#define R_AC CONFIG_CHARGER_SENSE_RESISTOR_AC -#define REG_TO_CURRENT(REG, RS) ((REG) * DEFAULT_SENSE_RESISTOR / (RS)) -#define CURRENT_TO_REG(CUR, RS) ((CUR) * (RS) / DEFAULT_SENSE_RESISTOR) - -/* - * charge voltage bitmask: 0111 1111 1111 0000 - * charge current bitmask: 0001 1111 1100 0000 - * input current bitmask : 0001 1111 1000 0000 - */ -static const struct charger_info bq24707a_charger_info = { - .name = "bq24707A", - .voltage_max = 19200, - .voltage_min = 1024, - .voltage_step = 16, - .current_max = REG_TO_CURRENT(0x1fc0, R_SNS), - .current_min = REG_TO_CURRENT(0x40, R_SNS), - .current_step = REG_TO_CURRENT(0x40, R_SNS), - .input_current_max = REG_TO_CURRENT(0x1F80, R_AC), - .input_current_min = REG_TO_CURRENT(0x80, R_AC), - .input_current_step = REG_TO_CURRENT(0x80, R_AC), -}; - -/* bq24707a specific interfaces */ - -static inline int sbc_read(int cmd, int *param) -{ - return i2c_read16(I2C_PORT_CHARGER, CHARGER_ADDR, cmd, param); -} - -static inline int sbc_write(int cmd, int param) -{ - return i2c_write16(I2C_PORT_CHARGER, CHARGER_ADDR, cmd, param); -} - -int charger_set_input_current(int input_current) -{ - return sbc_write(BQ24707_INPUT_CURRENT, - CURRENT_TO_REG(input_current, R_AC)); -} - -int charger_get_input_current(int *input_current) -{ - int rv; - int reg; - - rv = sbc_read(BQ24707_INPUT_CURRENT, ®); - if (rv) - return rv; - - *input_current = REG_TO_CURRENT(reg, R_AC); - - return EC_SUCCESS; -} - -int charger_manufacturer_id(int *id) -{ - return sbc_read(BQ24707_MANUFACTURE_ID, id); -} - -int charger_device_id(int *id) -{ - return sbc_read(BQ24707_DEVICE_ID, id); -} - -int charger_get_option(int *option) -{ - return sbc_read(BQ24707_CHARGE_OPTION, option); -} - -int charger_set_option(int option) -{ - return sbc_write(BQ24707_CHARGE_OPTION, option); -} - -/* Charger interfaces */ - -const struct charger_info *charger_get_info(void) -{ - return &bq24707a_charger_info; -} - -int charger_get_status(int *status) -{ - int rv; - int option; - - rv = charger_get_option(&option); - if (rv) - return rv; - - /* Default status */ - *status = CHARGER_LEVEL_2; - - if (option & OPTION_CHARGE_INHIBIT) - *status |= CHARGER_CHARGE_INHIBITED; - - return EC_SUCCESS; -} - -int charger_set_mode(int mode) -{ - int rv; - int option; - - rv = charger_get_option(&option); - if (rv) - return rv; - - if (mode & CHARGE_FLAG_INHIBIT_CHARGE) - option |= OPTION_CHARGE_INHIBIT; - else - option &= ~OPTION_CHARGE_INHIBIT; - return charger_set_option(option); -} - -int charger_get_current(int *current) -{ - int rv; - int reg; - - rv = sbc_read(SB_CHARGING_CURRENT, ®); - if (rv) - return rv; - - *current = REG_TO_CURRENT(reg, R_SNS); - return EC_SUCCESS; -} - -int charger_set_current(int current) -{ - current = charger_closest_current(current); - - return sbc_write(SB_CHARGING_CURRENT, CURRENT_TO_REG(current, R_SNS)); -} - -int charger_get_voltage(int *voltage) -{ - return sbc_read(SB_CHARGING_VOLTAGE, voltage); -} - -int charger_set_voltage(int voltage) -{ - return sbc_write(SB_CHARGING_VOLTAGE, voltage); -} - -/* Charging power state initialization */ -int charger_post_init(void) -{ - /* - * Note: bq24725 power on reset state is: - * watch dog timer = 175 sec - * input current limit = ~1/2 maximum setting - * charging voltage = 0 mV - * charging current = 0 mA - * IOUT = 20x adapter current sense - */ - - /* Set charger input current limit */ - return charger_set_input_current(CONFIG_CHARGER_INPUT_CURRENT); -} diff --git a/driver/charger/bq24707a.h b/driver/charger/bq24707a.h deleted file mode 100644 index c26a0eea35..0000000000 --- a/driver/charger/bq24707a.h +++ /dev/null @@ -1,44 +0,0 @@ -/* Copyright 2012 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. - * - * TI bq24707A battery charger driver. - */ - -#ifndef __CROS_EC_BQ24707A_H -#define __CROS_EC_BQ24707A_H - -/* Chip specific commands */ -#define BQ24707_CHARGE_OPTION 0x12 -#define BQ24707_INPUT_CURRENT 0x3f -#define BQ24707_MANUFACTURE_ID 0xfe -#define BQ24707_DEVICE_ID 0xff - -/* ChargeOption 0x12 */ -#define OPTION_CHARGE_INHIBIT BIT(0) -#define OPTION_ACOC_THRESHOLD (3 << 1) -#define OPTION_COMPARATOR_THRESHOLD BIT(4) -#define OPTION_IOUT_SELECTION BIT(5) -#define OPTION_IFAULT_HI_THRESHOLD (3 << 7) -#define OPTION_EMI_FREQ_ENABLE BIT(9) -#define OPTION_EMI_FREQ_ADJ BIT(10) -#define OPTION_WATCHDOG_TIMER (3 << 13) -#define OPTION_AOC_DELITCH_TIME BIT(15) -/* OPTION_ACOC_THRESHOLD */ -#define ACOC_THRESHOLD_DISABLE (0 << 1) -#define ACOC_THRESHOLD_133X BIT(1) -#define ACOC_THRESHOLD_166X_DEFAULT (2 << 1) -#define ACOC_THRESHOLD_222X (3 << 1) -/* OPTION_IFAULT_HI_THRESHOLD */ -#define IFAULT_THRESHOLD_300MV (0 << 7) -#define IFAULT_THRESHOLD_500MV BIT(7) -#define IFAULT_THRESHOLD_700MV_DEFAULT (2 << 7) -#define IFAULT_THRESHOLD_900MV (3 << 7) -/* OPTION_WATCHDOG_TIMER */ -#define CHARGE_WATCHDOG_DISABLE (0 << 13) -#define CHARGE_WATCHDOG_44SEC BIT(13) -#define CHARGE_WATCHDOG_88SEC (2 << 13) -#define CHARGE_WATCHDOG_175SEC_DEFAULT (3 << 13) - -#endif /* __CROS_EC_BQ24707A_H */ - diff --git a/driver/charger/bq24715.c b/driver/charger/bq24715.c deleted file mode 100644 index 8a8d9b894f..0000000000 --- a/driver/charger/bq24715.c +++ /dev/null @@ -1,228 +0,0 @@ -/* Copyright 2013 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. - * - * TI bq24715 battery charger driver. - */ - -#include "battery_smart.h" -#include "bq24715.h" -#include "charger.h" -#include "console.h" -#include "common.h" -#include "i2c.h" -#include "util.h" - -/* Sense resistor configurations and macros */ -#define DEFAULT_SENSE_RESISTOR 10 -#define R_SNS CONFIG_CHARGER_SENSE_RESISTOR -#define R_AC CONFIG_CHARGER_SENSE_RESISTOR_AC -#define REG_TO_CURRENT(REG, RS) ((REG) * DEFAULT_SENSE_RESISTOR / (RS)) -#define CURRENT_TO_REG(CUR, RS) ((CUR) * (RS) / DEFAULT_SENSE_RESISTOR) - -/* Note: it is assumed that the sense resistors are 10mOhm. */ - -static const struct charger_info bq24725_charger_info = { - .name = "bq24715", - .voltage_max = CHARGE_V_MAX, - .voltage_min = CHARGE_V_MIN, - .voltage_step = CHARGE_V_STEP, - .current_max = REG_TO_CURRENT(CHARGE_I_MAX, R_SNS), - .current_min = REG_TO_CURRENT(CHARGE_I_MIN, R_SNS), - .current_step = REG_TO_CURRENT(CHARGE_I_STEP, R_SNS), - .input_current_max = REG_TO_CURRENT(INPUT_I_MAX, R_AC), - .input_current_min = REG_TO_CURRENT(INPUT_I_MIN, R_AC), - .input_current_step = REG_TO_CURRENT(INPUT_I_STEP, R_AC), -}; - -static inline int sbc_read(int cmd, int *param) -{ - return i2c_read16(I2C_PORT_CHARGER, CHARGER_ADDR_FLAGS, - cmd, param); -} - -static inline int sbc_write(int cmd, int param) -{ - return i2c_write16(I2C_PORT_CHARGER, CHARGER_ADDR_FLAGS, - cmd, param); -} - -int charger_set_input_current(int input_current) -{ - return sbc_write(BQ24715_INPUT_CURRENT, - CURRENT_TO_REG(input_current, R_AC)); -} - -int charger_get_input_current(int *input_current) -{ - int rv; - int reg; - - rv = sbc_read(BQ24715_INPUT_CURRENT, ®); - if (rv) - return rv; - - *input_current = REG_TO_CURRENT(reg, R_AC); - - return EC_SUCCESS; -} - -int charger_manufacturer_id(int *id) -{ - return sbc_read(BQ24715_MANUFACTURER_ID, id); -} - -int charger_device_id(int *id) -{ - return sbc_read(BQ24715_DEVICE_ID, id); -} - -int charger_get_option(int *option) -{ - return sbc_read(BQ24715_CHARGE_OPTION, option); -} - -int charger_set_option(int option) -{ - return sbc_write(BQ24715_CHARGE_OPTION, option); -} - -/* Charger interfaces */ - -const struct charger_info *charger_get_info(void) -{ - return &bq24725_charger_info; -} - -int charger_get_status(int *status) -{ - int rv; - int option; - - rv = charger_get_option(&option); - if (rv) - return rv; - - /* Default status */ - *status = CHARGER_LEVEL_2; - - if ((option & OPT_CHARGE_INHIBIT_MASK) == OPT_CHARGE_DISABLE) - *status |= CHARGER_CHARGE_INHIBITED; - - return EC_SUCCESS; -} - -int charger_set_mode(int mode) -{ - int rv; - int option; - - rv = charger_get_option(&option); - if (rv) - return rv; - - option &= ~OPT_CHARGE_INHIBIT_MASK; - if (mode & CHARGE_FLAG_INHIBIT_CHARGE) - option |= OPT_CHARGE_DISABLE; - else - option |= OPT_CHARGE_ENABLE; - return charger_set_option(option); -} - -int charger_get_current(int *current) -{ - int rv; - int reg; - - rv = sbc_read(SB_CHARGING_CURRENT, ®); - if (rv) - return rv; - - *current = REG_TO_CURRENT(reg, R_SNS); - return EC_SUCCESS; -} - -int charger_set_current(int current) -{ - current = charger_closest_current(current); - - return sbc_write(SB_CHARGING_CURRENT, CURRENT_TO_REG(current, R_SNS)); -} - -/* The voltage setting needs to be cached to work with the current - * charging infrastructure and state machine. The reason is that - * the state machine expects to be able to set a 0V charging voltage. - * The bq24715 does not allow this in the hardware register. Therefore - * 0V is handled specially to appease the state machine. */ -static int cached_voltage; - -int charger_get_voltage(int *voltage) -{ - int ret; - - if (cached_voltage == 0) { - *voltage = cached_voltage; - return EC_SUCCESS; - } - - ret = sbc_read(SB_CHARGING_VOLTAGE, &cached_voltage); - - if (ret == EC_SUCCESS) - *voltage = cached_voltage; - - return ret; -} - -int charger_set_voltage(int voltage) -{ - cached_voltage = voltage; - return sbc_write(SB_CHARGING_VOLTAGE, voltage); -} - -/* Charging power state initialization */ -int charger_post_init(void) -{ - int rv; - int option; - - rv = charger_get_option(&option); - if (rv) - return rv; - - /* Don't be noisy */ - option |= OPT_AUDIO_FREQ_40KHZ_LIMIT; - - /* Always monitor adapter current (40X multiplier). */ - option |= OPT_FIX_IOUT_ALWAYS; - option &= ~OPT_IOUT_MASK; - option &= ~OPT_LEARN_MASK; - - /* Enable dynamic power management */ - option |= OPT_IDPM_ENABLE; - - rv = charger_set_option(option); - if (rv) - return rv; - - rv = charger_set_input_current(CONFIG_CHARGER_INPUT_CURRENT); - return rv; -} - -int charger_discharge_on_ac(int enable) -{ - int rv; - int option; - - rv = charger_get_option(&option); - if (rv) - return rv; - - option &= ~OPT_LEARN_MASK; - if (enable) - option |= OPT_LEARN_ENABLE; - else - option |= OPT_LEARN_DISABLE; - rv = charger_set_option(option); - - return rv; -} diff --git a/driver/charger/bq24715.h b/driver/charger/bq24715.h deleted file mode 100644 index ca07da053f..0000000000 --- a/driver/charger/bq24715.h +++ /dev/null @@ -1,130 +0,0 @@ -/* Copyright 2012 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. - * - * TI bq24715 battery charger driver. - */ - -#ifndef __CROS_EC_BQ24715_H -#define __CROS_EC_BQ24715_H - -/* NOTES: - * If battery is not present keep charge current register (0x14) at 0. - * Max charge voltage (0x15) needs to be programmed before 0x14. - */ - -/* Chip specific registers */ -#define BQ24715_CHARGE_OPTION 0x12 -#define BQ24715_CHARGE_CURRENT 0x14 -#define BQ24715_MAX_CHARGE_VOLTAGE 0x15 -#define BQ24715_MIN_SYSTEM_VOLTAGE 0x3e -#define BQ24715_INPUT_CURRENT 0x3f -#define BQ24715_MANUFACTURER_ID 0xfe -#define BQ24715_DEVICE_ID 0xff - -/* ChargeOption Register - 0x12 */ -#define OPT_LOWPOWER_MASK BIT(15) -#define OPT_LOWPOWER_DSCHRG_I_MON_ON (0 << 15) -#define OPT_LOWPOWER_DSCHRG_I_MON_OFF BIT(15) -#define OPT_WATCHDOG_MASK (3 << 13) -#define OPT_WATCHDOG_DISABLE (0 << 13) -#define OPT_WATCHDOG_44SEC BIT(13) -#define OPT_WATCHDOG_88SEC (2 << 13) -#define OPT_WATCHDOG_175SEC (3 << 13) -#define OPT_SYSOVP_MASK BIT(12) -#define OPT_SYSOVP_15P1_3SEC_10P1_2SEC (0 << 12) -#define OPT_SYSOVP_17P0_3SEC_11P3_2SEC BIT(12) -#define OPT_SYSOVP_STATUS_MASK BIT(11) -#define OPT_SYSOVP_STATUS BIT(11) -#define OPT_AUDIO_FREQ_LIMIT_MASK BIT(10) -#define OPT_AUDIO_FREQ_NO_LIMIT (0 << 10) -#define OPT_AUDIO_FREQ_40KHZ_LIMIT BIT(10) -#define OPT_SWITCH_FREQ_MASK (3 << 8) -#define OPT_SWITCH_FREQ_600KHZ (0 << 8) -#define OPT_SWITCH_FREQ_800KHZ BIT(8) -#define OPT_SWITCH_FREQ_1MHZ (2 << 8) -#define OPT_SWITCH_FREQ_800KHZ_DUP (3 << 8) -#define OPT_ACOC_MASK BIT(7) -#define OPT_ACOC_DISABLED (0 << 7) -#define OPT_ACOC_333PCT_IPDM BIT(7) -#define OPT_LSFET_OCP_MASK BIT(6) -#define OPT_LSFET_OCP_250MV (0 << 6) -#define OPT_LSFET_OCP_350MV BIT(6) -#define OPT_LEARN_MASK BIT(5) -#define OPT_LEARN_DISABLE (0 << 5) -#define OPT_LEARN_ENABLE BIT(5) -#define OPT_IOUT_MASK BIT(4) -#define OPT_IOUT_40X (0 << 4) -#define OPT_IOUT_16X BIT(4) -#define OPT_FIX_IOUT_MASK BIT(3) -#define OPT_FIX_IOUT_IDPM_EN (0 << 3) -#define OPT_FIX_IOUT_ALWAYS BIT(3) -#define OPT_LDO_MODE_MASK BIT(2) -#define OPT_LDO_DISABLE (0 << 2) -#define OPT_LDO_ENABLE BIT(2) -#define OPT_IDPM_MASK BIT(1) -#define OPT_IDPM_DISABLE (0 << 1) -#define OPT_IDPM_ENABLE BIT(1) -#define OPT_CHARGE_INHIBIT_MASK BIT(0) -#define OPT_CHARGE_ENABLE (0 << 0) -#define OPT_CHARGE_DISABLE BIT(0) - - -/* ChargeCurrent Register - 0x14 - * The ChargeCurrent register controls a DAC. Therefore - * the below definitions are cummulative. */ -#define CHARGE_I_64MA BIT(6) -#define CHARGE_I_128MA BIT(7) -#define CHARGE_I_256MA BIT(8) -#define CHARGE_I_512MA BIT(9) -#define CHARGE_I_1024MA BIT(10) -#define CHARGE_I_2048MA BIT(11) -#define CHARGE_I_4096MA BIT(12) -#define CHARGE_I_OFF (0) -#define CHARGE_I_MIN (128) -#define CHARGE_I_MAX (8128) -#define CHARGE_I_STEP (64) - -/* MaxChargeVoltage Register - 0x15 - * The MaxChargeVoltage register controls a DAC. Therefore - * the below definitions are cummulative. */ -#define CHARGE_V_16MV BIT(4) -#define CHARGE_V_32MV BIT(5) -#define CHARGE_V_64MV BIT(6) -#define CHARGE_V_128MV BIT(7) -#define CHARGE_V_256MV BIT(8) -#define CHARGE_V_512MV BIT(9) -#define CHARGE_V_1024MV BIT(10) -#define CHARGE_V_2048MV BIT(11) -#define CHARGE_V_4096MV BIT(12) -#define CHARGE_V_8192MV BIT(13) -#define CHARGE_V_MIN (4096) -#define CHARGE_V_MAX (0x3ff0) -#define CHARGE_V_STEP (16) - -/* MinSystemVoltage Register - 0x3e - * The MinSystemVoltage register controls a DAC. Therefore - * the below definitions are cummulative. */ -#define MIN_SYS_V_256MV BIT(8) -#define MIN_SYS_V_512MV BIT(9) -#define MIN_SYS_V_1024MV BIT(10) -#define MIN_SYS_V_2048MV BIT(11) -#define MIN_SYS_V_4096MV BIT(12) -#define MIN_SYS_V_8192MV BIT(13) -#define MIN_SYS_V_MIN (4096) - -/* InputCurrent Register - 0x3f - * The InputCurrent register controls a DAC. Therefore - * the below definitions are cummulative. */ -#define INPUT_I_64MA BIT(6) -#define INPUT_I_128MA BIT(7) -#define INPUT_I_256MA BIT(8) -#define INPUT_I_512MA BIT(9) -#define INPUT_I_1024MA BIT(10) -#define INPUT_I_2048MA BIT(11) -#define INPUT_I_4096MA BIT(12) -#define INPUT_I_MIN (128) -#define INPUT_I_MAX (8064) -#define INPUT_I_STEP (64) - -#endif /* __CROS_EC_BQ24715_H */ diff --git a/driver/charger/bq24725.c b/driver/charger/bq24725.c deleted file mode 100644 index 48f53a05c4..0000000000 --- a/driver/charger/bq24725.c +++ /dev/null @@ -1,194 +0,0 @@ -/* Copyright 2012 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. - * - * TI bq24725 battery charger driver. - */ - -#include "battery_smart.h" -#include "bq24725.h" -#include "charger.h" -#include "console.h" -#include "common.h" -#include "util.h" - -/* Sense resistor configurations and macros */ -#define DEFAULT_SENSE_RESISTOR 10 -#define R_SNS CONFIG_CHARGER_SENSE_RESISTOR -#define R_AC CONFIG_CHARGER_SENSE_RESISTOR_AC -#define REG_TO_CURRENT(REG, RS) ((REG) * DEFAULT_SENSE_RESISTOR / (RS)) -#define CURRENT_TO_REG(CUR, RS) ((CUR) * (RS) / DEFAULT_SENSE_RESISTOR) - -/* Charger information - * charge voltage bitmask: 0111 1111 1111 0000 - * charge current bitmask: 0001 1111 1000 0000 - * input current bitmask : 0000 0000 1000 0000 - */ -static const struct charger_info bq24725_charger_info = { - .name = "bq24725", - .voltage_max = 19200, - .voltage_min = 1024, - .voltage_step = 16, - .current_max = REG_TO_CURRENT(8128, R_SNS), - .current_min = REG_TO_CURRENT(128, R_SNS), - .current_step = REG_TO_CURRENT(128, R_SNS), - .input_current_max = REG_TO_CURRENT(8064, R_AC), - .input_current_min = REG_TO_CURRENT(128, R_AC), - .input_current_step = REG_TO_CURRENT(128, R_AC), -}; - -/* bq24725 specific interfaces */ - -int charger_set_input_current(int input_current) -{ - return sbc_write(BQ24725_INPUT_CURRENT, - CURRENT_TO_REG(input_current, R_AC)); -} - -int charger_get_input_current(int *input_current) -{ - int rv; - int reg; - - rv = sbc_read(BQ24725_INPUT_CURRENT, ®); - if (rv) - return rv; - - *input_current = REG_TO_CURRENT(reg, R_AC); - - return EC_SUCCESS; -} - -int charger_manufacturer_id(int *id) -{ - return sbc_read(BQ24725_MANUFACTURE_ID, id); -} - -int charger_device_id(int *id) -{ - return sbc_read(BQ24725_DEVICE_ID, id); -} - -int charger_get_option(int *option) -{ - return sbc_read(BQ24725_CHARGE_OPTION, option); -} - -int charger_set_option(int option) -{ - return sbc_write(BQ24725_CHARGE_OPTION, option); -} - -/* Charger interfaces */ - -const struct charger_info *charger_get_info(void) -{ - return &bq24725_charger_info; -} - -int charger_get_status(int *status) -{ - int rv; - int option; - - rv = charger_get_option(&option); - if (rv) - return rv; - - /* Default status */ - *status = CHARGER_LEVEL_2; - - if (option & OPTION_CHARGE_INHIBIT) - *status |= CHARGER_CHARGE_INHIBITED; - - return EC_SUCCESS; -} - -int charger_set_mode(int mode) -{ - int rv; - int option; - - rv = charger_get_option(&option); - if (rv) - return rv; - - if (mode & CHARGE_FLAG_INHIBIT_CHARGE) - option |= OPTION_CHARGE_INHIBIT; - else - option &= ~OPTION_CHARGE_INHIBIT; - return charger_set_option(option); -} - -int charger_get_current(int *current) -{ - int rv; - int reg; - - rv = sbc_read(SB_CHARGING_CURRENT, ®); - if (rv) - return rv; - - *current = REG_TO_CURRENT(reg, R_SNS); - return EC_SUCCESS; -} - -int charger_set_current(int current) -{ - current = charger_closest_current(current); - - return sbc_write(SB_CHARGING_CURRENT, CURRENT_TO_REG(current, R_SNS)); -} - -int charger_get_voltage(int *voltage) -{ - return sbc_read(SB_CHARGING_VOLTAGE, voltage); -} - -int charger_set_voltage(int voltage) -{ - return sbc_write(SB_CHARGING_VOLTAGE, voltage); -} - -/* Charging power state initialization */ -int charger_post_init(void) -{ - /* - * Note: bq24725 power on reset state is: - * watch dog timer = 175 sec - * input current limit = ~1/2 maximum setting - * charging voltage = 0 mV - * charging current = 0 mA - */ - - int rv, option; - - rv = charger_get_option(&option); - if (rv) - return rv; - - option &= ~OPTION_LEARN_ENABLE; - rv = charger_set_option(option); - if (rv) - return rv; - - /* Set charger input current limit */ - return charger_set_input_current(CONFIG_CHARGER_INPUT_CURRENT); -} - -int charger_discharge_on_ac(int enable) -{ - int rv; - int option; - - rv = charger_get_option(&option); - if (rv) - return rv; - - if (enable) - rv = charger_set_option(option | OPTION_LEARN_ENABLE); - else - rv = charger_set_option(option & ~OPTION_LEARN_ENABLE); - - return rv; -} diff --git a/driver/charger/bq24725.h b/driver/charger/bq24725.h deleted file mode 100644 index ad6c508a4f..0000000000 --- a/driver/charger/bq24725.h +++ /dev/null @@ -1,50 +0,0 @@ -/* Copyright 2012 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. - * - * TI bq24725 battery charger driver. - */ - -#ifndef __CROS_EC_BQ24725_H -#define __CROS_EC_BQ24725_H - -/* Chip specific commands */ -#define BQ24725_CHARGE_OPTION 0x12 -#define BQ24725_INPUT_CURRENT 0x3f -#define BQ24725_MANUFACTURE_ID 0xfe -#define BQ24725_DEVICE_ID 0xff - -/* ChargeOption 0x12 */ -#define OPTION_CHARGE_INHIBIT BIT(0) -#define OPTION_ACOC_THRESHOLD (3 << 1) -#define OPTION_IOUT_SELECTION BIT(5) -#define OPTION_LEARN_ENABLE BIT(6) -#define OPTION_IFAULT_HI_THRESHOLD (3 << 7) -#define OPTION_EMI_FREQ_ENABLE BIT(9) -#define OPTION_EMI_FREQ_ADJ BIT(10) -#define OPTION_BAT_DEPLETION_THRESHOLD (3 << 11) -#define OPTION_WATCHDOG_TIMER (3 << 13) -#define OPTION_AOC_DELITCH_TIME BIT(15) -/* OPTION_ACOC_THRESHOLD */ -#define ACOC_THRESHOLD_DISABLE (0 << 1) -#define ACOC_THRESHOLD_133X BIT(1) -#define ACOC_THRESHOLD_166X_DEFAULT (2 << 1) -#define ACOC_THRESHOLD_222X (3 << 1) -/* OPTION_IFAULT_HI_THRESHOLD */ -#define IFAULT_THRESHOLD_300MV (0 << 7) -#define IFAULT_THRESHOLD_500MV BIT(7) -#define IFAULT_THRESHOLD_700MV_DEFAULT (2 << 7) -#define IFAULT_THRESHOLD_900MV (3 << 7) -/* OPTION_BAT_DEPLETION_THRESHOLD */ -#define FALLING_THRESHOLD_5919 (0 << 11) -#define FALLING_THRESHOLD_6265 BIT(11) -#define FALLING_THRESHOLD_6655 (2 << 11) -#define FALLING_THRESHOLD_7097_DEFAULT (3 << 11) -/* OPTION_WATCHDOG_TIMER */ -#define CHARGE_WATCHDOG_DISABLE (0 << 13) -#define CHARGE_WATCHDOG_44SEC BIT(13) -#define CHARGE_WATCHDOG_88SEC (2 << 13) -#define CHARGE_WATCHDOG_175SEC_DEFAULT (3 << 13) - -#endif /* __CROS_EC_BQ24725_H */ - diff --git a/driver/charger/bq24735.c b/driver/charger/bq24735.c deleted file mode 100644 index 65fe353f9d..0000000000 --- a/driver/charger/bq24735.c +++ /dev/null @@ -1,205 +0,0 @@ -/* Copyright 2014 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. - * - * TI bq24735 battery charger driver. - */ - -#include "battery_smart.h" -#include "bq24735.h" -#include "charger.h" -#include "console.h" -#include "common.h" -#include "i2c.h" -#include "util.h" - -/* Sense resistor configurations and macros */ -#define DEFAULT_SENSE_RESISTOR 10 -#define R_SNS CONFIG_CHARGER_SENSE_RESISTOR -#define R_AC CONFIG_CHARGER_SENSE_RESISTOR_AC -#define REG_TO_CURRENT(REG, RS) ((REG) * DEFAULT_SENSE_RESISTOR / (RS)) -#define CURRENT_TO_REG(CUR, RS) ((CUR) * (RS) / DEFAULT_SENSE_RESISTOR) - -/* Charger information - * charge voltage bitmask: 0111 1111 1111 0000 - * charge current bitmask: 0001 1111 1000 0000 - * input current bitmask : 0000 0000 1000 0000 - */ -static const struct charger_info bq24735_charger_info = { - .name = "bq24735", - .voltage_max = 19200, - .voltage_min = 1024, - .voltage_step = 16, - .current_max = REG_TO_CURRENT(8128, R_SNS), - .current_min = REG_TO_CURRENT(128, R_SNS), - .current_step = REG_TO_CURRENT(128, R_SNS), - .input_current_max = REG_TO_CURRENT(8064, R_AC), - .input_current_min = REG_TO_CURRENT(128, R_AC), - .input_current_step = REG_TO_CURRENT(128, R_AC), -}; - -/* bq24735 specific interfaces */ - -static inline int sbc_read(int cmd, int *param) -{ - return i2c_read16(I2C_PORT_CHARGER, CHARGER_ADDR, cmd, param); -} - -static inline int sbc_write(int cmd, int param) -{ - return i2c_write16(I2C_PORT_CHARGER, CHARGER_ADDR, cmd, param); -} - -int charger_set_input_current(int input_current) -{ - return sbc_write(BQ24735_INPUT_CURRENT, - CURRENT_TO_REG(input_current, R_AC)); -} - -int charger_get_input_current(int *input_current) -{ - int rv; - int reg; - - rv = sbc_read(BQ24735_INPUT_CURRENT, ®); - if (rv) - return rv; - - *input_current = REG_TO_CURRENT(reg, R_AC); - - return EC_SUCCESS; -} - -int charger_manufacturer_id(int *id) -{ - return sbc_read(BQ24735_MANUFACTURE_ID, id); -} - -int charger_device_id(int *id) -{ - return sbc_read(BQ24735_DEVICE_ID, id); -} - -int charger_get_option(int *option) -{ - return sbc_read(BQ24735_CHARGE_OPTION, option); -} - -int charger_set_option(int option) -{ - return sbc_write(BQ24735_CHARGE_OPTION, option); -} - -/* Charger interfaces */ - -const struct charger_info *charger_get_info(void) -{ - return &bq24735_charger_info; -} - -int charger_get_status(int *status) -{ - int rv; - int option; - - rv = charger_get_option(&option); - if (rv) - return rv; - - /* Default status */ - *status = CHARGER_LEVEL_2; - - if (option & OPTION_CHARGE_INHIBIT) - *status |= CHARGER_CHARGE_INHIBITED; - - return EC_SUCCESS; -} - -int charger_set_mode(int mode) -{ - int rv; - int option; - - rv = charger_get_option(&option); - if (rv) - return rv; - - if (mode & CHARGE_FLAG_INHIBIT_CHARGE) - option |= OPTION_CHARGE_INHIBIT; - else - option &= ~OPTION_CHARGE_INHIBIT; - return charger_set_option(option); -} - -int charger_get_current(int *current) -{ - int rv; - int reg; - - rv = sbc_read(SB_CHARGING_CURRENT, ®); - if (rv) - return rv; - - *current = REG_TO_CURRENT(reg, R_SNS); - return EC_SUCCESS; -} - -int charger_set_current(int current) -{ - current = charger_closest_current(current); - - return sbc_write(SB_CHARGING_CURRENT, CURRENT_TO_REG(current, R_SNS)); -} - -int charger_get_voltage(int *voltage) -{ - return sbc_read(SB_CHARGING_VOLTAGE, voltage); -} - -int charger_set_voltage(int voltage) -{ - return sbc_write(SB_CHARGING_VOLTAGE, voltage); -} - -/* Charging power state initialization */ -int charger_post_init(void) -{ - /* - * Note: bq24735 power on reset state is: - * watch dog timer = 175 sec - * input current limit = ~1/2 maximum setting - * charging voltage = 0 mV - * charging current = 0 mA - */ - - int rv, option; - - rv = charger_get_option(&option); - if (rv) - return rv; - - option &= ~OPTION_LEARN_ENABLE; - rv = charger_set_option(option); - if (rv) - return rv; - - /* Set charger input current limit */ - return charger_set_input_current(CONFIG_CHARGER_INPUT_CURRENT); -} - -int charger_discharge_on_ac(int enable) -{ - int rv; - int option; - - rv = charger_get_option(&option); - if (rv) - return rv; - - if (enable) - rv = charger_set_option(option | OPTION_LEARN_ENABLE); - else - rv = charger_set_option(option & ~OPTION_LEARN_ENABLE); - - return rv; -} diff --git a/driver/charger/bq24735.h b/driver/charger/bq24735.h deleted file mode 100644 index 62d3365306..0000000000 --- a/driver/charger/bq24735.h +++ /dev/null @@ -1,57 +0,0 @@ -/* Copyright 2014 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. - * - * TI bq24735 battery charger driver. - */ - -#ifndef __CROS_EC_BQ24735_H -#define __CROS_EC_BQ24735_H - -/* Chip specific commands */ -#define BQ24735_CHARGE_OPTION 0x12 -#define BQ24735_INPUT_CURRENT 0x3f -#define BQ24735_MANUFACTURE_ID 0xfe -#define BQ24735_DEVICE_ID 0xff - -/* ChargeOption 0x12 */ -#define OPTION_CHARGE_INHIBIT BIT(0) -#define OPTION_ACOC_THRESHOLD BIT(1) -#define OPTION_BOOST_MODE_STATE BIT(2) -#define OPTION_BOOST_MODE_ENABLE BIT(3) -#define OPTION_ACDET_STATE BIT(4) -#define OPTION_IOUT_SELECTION BIT(5) -#define OPTION_LEARN_ENABLE BIT(6) -#define OPTION_IFAULT_LOW_THRESHOLD BIT(7) -#define OPTION_IFAULT_HI_ENABLE BIT(8) -#define OPTION_EMI_FREQ_ENABLE BIT(9) -#define OPTION_EMI_FREQ_ADJ BIT(10) -#define OPTION_BAT_DEPLETION_THRESHOLD (3 << 11) -#define OPTION_WATCHDOG_TIMER (3 << 13) -#define OPTION_ACPRES_DEGLITCH_TIME BIT(15) - -/* OPTION_ACOC_THRESHOLD */ -#define ACOC_THRESHOLD_DISABLE (0 << 1) -#define ACOC_THRESHOLD_133X BIT(1) - -/* OPTION_IFAULT_LOW_THRESHOLD */ -#define IFAULT_LOW_135MV_DEFAULT (0 << 7) -#define IFAULT_LOW_230MV BIT(7) - -/* OPTION_BAT_DEPLETION_THRESHOLD */ -#define FALLING_THRESHOLD_5919 (0 << 11) -#define FALLING_THRESHOLD_6265 BIT(11) -#define FALLING_THRESHOLD_6655 (2 << 11) -#define FALLING_THRESHOLD_7097_DEFAULT (3 << 11) - -/* OPTION_WATCHDOG_TIMER */ -#define CHARGE_WATCHDOG_DISABLE (0 << 13) -#define CHARGE_WATCHDOG_44SEC BIT(13) -#define CHARGE_WATCHDOG_88SEC (2 << 13) -#define CHARGE_WATCHDOG_175SEC_DEFAULT (3 << 13) - -/* OPTION_ACPRES_DEGLITCH_TIME */ -#define ACPRES_DEGLITCH_150MS (0 << 15) -#define ACPRES_DEGLITCH_1300MS_DEFAULT BIT(15) - -#endif /* __CROS_EC_BQ24735_H */ diff --git a/driver/charger/bq24738.c b/driver/charger/bq24738.c deleted file mode 100644 index 507ee3bf62..0000000000 --- a/driver/charger/bq24738.c +++ /dev/null @@ -1,189 +0,0 @@ -/* Copyright 2013 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. - * - * TI bq24738 battery charger driver. - */ - -#include "battery_smart.h" -#include "bq24738.h" -#include "charger.h" -#include "console.h" -#include "common.h" -#include "util.h" - -/* Sense resistor configurations and macros */ -#define DEFAULT_SENSE_RESISTOR 10 -#define R_SNS CONFIG_CHARGER_SENSE_RESISTOR -#define R_AC CONFIG_CHARGER_SENSE_RESISTOR_AC -#define REG_TO_CURRENT(REG, RS) ((REG) * DEFAULT_SENSE_RESISTOR / (RS)) -#define CURRENT_TO_REG(CUR, RS) ((CUR) * (RS) / DEFAULT_SENSE_RESISTOR) - -/* Charger information - * charge voltage bitmask: 0111 1111 1111 0000 - * charge current bitmask: 0001 1111 1100 0000 - * input current bitmask : 0000 0000 1000 0000 - */ -static const struct charger_info bq24738_charger_info = { - .name = "bq24738", - .voltage_max = 19200, - .voltage_min = 1024, - .voltage_step = 16, - .current_max = REG_TO_CURRENT(8128, R_SNS), - .current_min = REG_TO_CURRENT(128, R_SNS), - .current_step = REG_TO_CURRENT(64, R_SNS), - .input_current_max = REG_TO_CURRENT(8064, R_AC), - .input_current_min = REG_TO_CURRENT(128, R_AC), - .input_current_step = REG_TO_CURRENT(128, R_AC), -}; - -/* bq24738 specific interfaces */ - -int charger_set_input_current(int input_current) -{ - return sbc_write(BQ24738_INPUT_CURRENT, - CURRENT_TO_REG(input_current, R_AC)); -} - -int charger_get_input_current(int *input_current) -{ - int rv; - int reg; - - rv = sbc_read(BQ24738_INPUT_CURRENT, ®); - if (rv) - return rv; - - *input_current = REG_TO_CURRENT(reg, R_AC); - - return EC_SUCCESS; -} - -int charger_manufacturer_id(int *id) -{ - return sbc_read(BQ24738_MANUFACTURE_ID, id); -} - -int charger_device_id(int *id) -{ - return sbc_read(BQ24738_DEVICE_ID, id); -} - -int charger_get_option(int *option) -{ - return sbc_read(BQ24738_CHARGE_OPTION, option); -} - -int charger_set_option(int option) -{ - return sbc_write(BQ24738_CHARGE_OPTION, option); -} - -/* Charger interfaces */ - -const struct charger_info *charger_get_info(void) -{ - return &bq24738_charger_info; -} - -int charger_get_status(int *status) -{ - int rv; - int option; - - rv = charger_get_option(&option); - if (rv) - return rv; - - /* Default status */ - *status = CHARGER_LEVEL_2; - - if (option & OPTION_CHARGE_INHIBIT) - *status |= CHARGER_CHARGE_INHIBITED; - - return EC_SUCCESS; -} - -int charger_set_mode(int mode) -{ - int rv; - int option; - - rv = charger_get_option(&option); - if (rv) - return rv; - - if (mode & CHARGE_FLAG_INHIBIT_CHARGE) - option |= OPTION_CHARGE_INHIBIT; - else - option &= ~OPTION_CHARGE_INHIBIT; - return charger_set_option(option); -} - -int charger_get_current(int *current) -{ - int rv; - int reg; - - rv = sbc_read(SB_CHARGING_CURRENT, ®); - if (rv) - return rv; - - *current = REG_TO_CURRENT(reg, R_SNS); - return EC_SUCCESS; -} - -int charger_set_current(int current) -{ - current = charger_closest_current(current); - - return sbc_write(SB_CHARGING_CURRENT, CURRENT_TO_REG(current, R_SNS)); -} - -int charger_get_voltage(int *voltage) -{ - return sbc_read(SB_CHARGING_VOLTAGE, voltage); -} - -int charger_set_voltage(int voltage) -{ - return sbc_write(SB_CHARGING_VOLTAGE, voltage); -} - -/* Charging power state initialization */ -int charger_post_init(void) -{ - int rv; - int val; - - /* Disable IFAULT_HI. See crosbug.com/p/19868 */ - rv = charger_get_option(&val); - if (rv) - return rv; - val &= ~OPTION_IFAULT_HI_ENABLE; - val &= ~OPTION_LEARN_ENABLE; - rv = charger_set_option(val); - if (rv) - return rv; - - /* Set charger input current limit */ - rv = charger_set_input_current(CONFIG_CHARGER_INPUT_CURRENT); - return rv; -} - -int charger_discharge_on_ac(int enable) -{ - int rv; - int option; - - rv = charger_get_option(&option); - if (rv) - return rv; - - if (enable) - rv = charger_set_option(option | OPTION_LEARN_ENABLE); - else - rv = charger_set_option(option & ~OPTION_LEARN_ENABLE); - - return rv; -} diff --git a/driver/charger/bq24738.h b/driver/charger/bq24738.h deleted file mode 100644 index c06d1729b0..0000000000 --- a/driver/charger/bq24738.h +++ /dev/null @@ -1,57 +0,0 @@ -/* Copyright 2013 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. - * - * TI bq24738 battery charger driver. - */ - -#ifndef __CROS_EC_BQ24738_H -#define __CROS_EC_BQ24738_H - -/* Chip specific commands */ -#define BQ24738_CHARGE_OPTION 0x12 -#define BQ24738_INPUT_CURRENT 0x3f -#define BQ24738_MANUFACTURE_ID 0xfe -#define BQ24738_DEVICE_ID 0xff - -/* ChargeOption 0x12 */ -#define OPTION_CHARGE_INHIBIT BIT(0) -#define OPTION_ACOC_THRESHOLD BIT(1) -#define OPTION_BOOST_MODE_STATE BIT(2) -#define OPTION_BOOST_MODE_ENABLE BIT(3) -#define OPTION_ACDET_STATE BIT(4) -#define OPTION_IOUT_SELECTION BIT(5) -#define OPTION_LEARN_ENABLE BIT(6) -#define OPTION_IFAULT_LOW_THRESHOLD BIT(7) -#define OPTION_IFAULT_HI_ENABLE BIT(8) -#define OPTION_EMI_FREQ_ENABLE BIT(9) -#define OPTION_EMI_FREQ_ADJ BIT(10) -#define OPTION_BAT_DEPLETION_THRESHOLD (3 << 11) -#define OPTION_WATCHDOG_TIMER (3 << 13) -#define OPTION_ACPRES_DEGLITCH_TIME BIT(15) - -/* OPTION_ACOC_THRESHOLD */ -#define ACOC_THRESHOLD_DISABLE (0 << 1) -#define ACOC_THRESHOLD_133X BIT(1) - -/* OPTION_IFAULT_LOW_THRESHOLD */ -#define IFAULT_LOW_135MV_DEFAULT (0 << 7) -#define IFAULT_LOW_230MV BIT(7) - -/* OPTION_BAT_DEPLETION_THRESHOLD */ -#define FALLING_THRESHOLD_5919 (0 << 11) -#define FALLING_THRESHOLD_6265 BIT(11) -#define FALLING_THRESHOLD_6655 (2 << 11) -#define FALLING_THRESHOLD_7097_DEFAULT (3 << 11) - -/* OPTION_WATCHDOG_TIMER */ -#define CHARGE_WATCHDOG_DISABLE (0 << 13) -#define CHARGE_WATCHDOG_44SEC BIT(13) -#define CHARGE_WATCHDOG_88SEC (2 << 13) -#define CHARGE_WATCHDOG_175SEC_DEFAULT (3 << 13) - -/* OPTION_ACPRES_DEGLITCH_TIME */ -#define ACPRES_DEGLITCH_150MS (0 << 15) -#define ACPRES_DEGLITCH_1300MS_DEFAULT BIT(15) - -#endif /* __CROS_EC_BQ24738_H */ diff --git a/driver/charger/bq24773.c b/driver/charger/bq24773.c deleted file mode 100644 index 4cd85b5ff1..0000000000 --- a/driver/charger/bq24773.c +++ /dev/null @@ -1,249 +0,0 @@ -/* Copyright 2014 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. - * - * TI bq24773 battery charger driver. - */ - -#include "battery_smart.h" -#include "bq24773.h" -#include "charger.h" -#include "console.h" -#include "common.h" -#include "util.h" - -/* - * on the I2C version of the charger, - * some registers are 8-bit only (eg input current) - * and they are shifted by 6 bits compared to the SMBUS version (bq24770). - */ -#define REG8_SHIFT 6 -#define R8 (1 << (REG8_SHIFT)) -/* Sense resistor configurations and macros */ -#define DEFAULT_SENSE_RESISTOR 10 -#define R_SNS CONFIG_CHARGER_SENSE_RESISTOR -#define R_AC (CONFIG_CHARGER_SENSE_RESISTOR_AC) -#define REG_TO_CURRENT(REG, RS) ((REG) * DEFAULT_SENSE_RESISTOR / (RS)) -#define CURRENT_TO_REG(CUR, RS) ((CUR) * (RS) / DEFAULT_SENSE_RESISTOR) -#define REG8_TO_CURRENT(REG, RS) ((REG) * DEFAULT_SENSE_RESISTOR / (RS) * R8) -#define CURRENT_TO_REG8(CUR, RS) ((CUR) * (RS) / DEFAULT_SENSE_RESISTOR / R8) - -/* Charger parameters */ -static const struct charger_info bq2477x_charger_info = { - .name = CHARGER_NAME, - .voltage_max = CHARGE_V_MAX, - .voltage_min = CHARGE_V_MIN, - .voltage_step = CHARGE_V_STEP, - .current_max = REG_TO_CURRENT(CHARGE_I_MAX, R_SNS), - .current_min = REG_TO_CURRENT(CHARGE_I_MIN, R_SNS), - .current_step = REG_TO_CURRENT(CHARGE_I_STEP, R_SNS), - .input_current_max = REG_TO_CURRENT(INPUT_I_MAX, R_AC), - .input_current_min = REG_TO_CURRENT(INPUT_I_MIN, R_AC), - .input_current_step = REG_TO_CURRENT(INPUT_I_STEP, R_AC), -}; - -/* chip specific interfaces */ - -int charger_set_input_current(int input_current) -{ -#ifdef CONFIG_CHARGER_BQ24770 - return raw_write16(REG_INPUT_CURRENT, - CURRENT_TO_REG(input_current, R_AC)); -#elif defined(CONFIG_CHARGER_BQ24773) - return raw_write8(REG_INPUT_CURRENT, - CURRENT_TO_REG8(input_current, R_AC)); -#endif -} - -int charger_get_input_current(int *input_current) -{ - int rv; - int reg; - -#ifdef CONFIG_CHARGER_BQ24770 - rv = raw_read16(REG_INPUT_CURRENT, ®); -#elif defined(CONFIG_CHARGER_BQ24773) - rv = raw_read8(REG_INPUT_CURRENT, ®); -#endif - if (rv) - return rv; - -#ifdef CONFIG_CHARGER_BQ24770 - *input_current = REG_TO_CURRENT(reg, R_AC); -#elif defined(CONFIG_CHARGER_BQ24773) - *input_current = REG8_TO_CURRENT(reg, R_AC); -#endif - return EC_SUCCESS; -} - -int charger_manufacturer_id(int *id) -{ -#ifdef CONFIG_CHARGER_BQ24770 - return raw_read16(REG_MANUFACTURE_ID, id); -#elif defined(CONFIG_CHARGER_BQ24773) - *id = 0x40; /* TI */ - return EC_SUCCESS; -#endif -} - -int charger_device_id(int *id) -{ -#ifdef CONFIG_CHARGER_BQ24770 - return raw_read16(REG_DEVICE_ADDRESS, id); -#elif defined(CONFIG_CHARGER_BQ24773) - return raw_read8(REG_DEVICE_ADDRESS, id); -#endif -} - -int charger_get_option(int *option) -{ - return raw_read16(REG_CHARGE_OPTION0, option); -} - -int charger_set_option(int option) -{ - return raw_write16(REG_CHARGE_OPTION0, option); -} - -/* Charger interfaces */ - -const struct charger_info *charger_get_info(void) -{ - return &bq2477x_charger_info; -} - -int charger_get_status(int *status) -{ - int rv; - int option; - - rv = charger_get_option(&option); - if (rv) - return rv; - - /* Default status */ - *status = CHARGER_LEVEL_2; - - if (option & OPTION0_CHARGE_INHIBIT) - *status |= CHARGER_CHARGE_INHIBITED; - - return EC_SUCCESS; -} - -int charger_set_mode(int mode) -{ - int rv; - int option; - - rv = charger_get_option(&option); - if (rv) - return rv; - - if (mode & CHARGE_FLAG_INHIBIT_CHARGE) - option |= OPTION0_CHARGE_INHIBIT; - else - option &= ~OPTION0_CHARGE_INHIBIT; - return charger_set_option(option); -} - -int charger_get_current(int *current) -{ - int rv; - int reg; - - rv = raw_read16(REG_CHARGE_CURRENT, ®); - - if (rv) - return rv; - - *current = REG_TO_CURRENT(reg, R_SNS); - return EC_SUCCESS; -} - -int charger_set_current(int current) -{ - current = charger_closest_current(current); - return raw_write16(REG_CHARGE_CURRENT, CURRENT_TO_REG(current, R_SNS)); -} - -int charger_get_voltage(int *voltage) -{ - return raw_read16(REG_MAX_CHARGE_VOLTAGE, voltage); -} - -int charger_set_voltage(int voltage) -{ - voltage = charger_closest_voltage(voltage); - return raw_write16(REG_MAX_CHARGE_VOLTAGE, voltage); -} - -/* Charging power state initialization */ -int charger_post_init(void) -{ - int rv, option; -#ifdef CONFIG_CHARGER_ILIM_PIN_DISABLED - int option2; -#endif - - rv = charger_get_option(&option); - if (rv) - return rv; - - option &= ~OPTION0_LEARN_ENABLE; - rv = charger_set_option(option); - if (rv) - return rv; - -#ifndef BOARD_SAMUS - /* Turn off PROCHOT warning */ - rv = raw_read16(REG_PROCHOT_OPTION1, &option); - if (rv) - return rv; - - option &= ~PROCHOT_OPTION1_SELECTOR_MASK; - - rv = raw_write16(REG_PROCHOT_OPTION1, option); -#else - /* On Samus, use PROCHOT warning to detect charging problems */ - /* Turn on PROCHOT warning */ - rv = raw_write16(REG_PROCHOT_OPTION1, 0x8120); - /* Set PROCHOT ICRIT warning when IADP is >120% of IDPM */ - rv |= raw_write16(REG_PROCHOT_OPTION0, 0x1b54); -#endif - - if (rv) - return rv; - -#ifdef CONFIG_CHARGER_ILIM_PIN_DISABLED - /* Read the external ILIM pin enabled flag. */ - rv = raw_read16(REG_CHARGE_OPTION2, &option2); - if (rv) - return rv; - - /* Set ILIM pin disabled if it is currently enabled. */ - if (option2 & OPTION2_EN_EXTILIM) { - option2 &= ~OPTION2_EN_EXTILIM; - rv = raw_write16(REG_CHARGE_OPTION2, option2); - } - return rv; -#else - return EC_SUCCESS; -#endif -} - -int charger_discharge_on_ac(int enable) -{ - int rv; - int option; - - rv = charger_get_option(&option); - if (rv) - return rv; - - if (enable) - rv = charger_set_option(option | OPTION0_LEARN_ENABLE); - else - rv = charger_set_option(option & ~OPTION0_LEARN_ENABLE); - - return rv; -} diff --git a/driver/charger/bq24773.h b/driver/charger/bq24773.h deleted file mode 100644 index 910ad8da25..0000000000 --- a/driver/charger/bq24773.h +++ /dev/null @@ -1,131 +0,0 @@ -/* Copyright 2014 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. - * - * TI bq24773 battery charger driver. - */ - -#ifndef __CROS_EC_BQ24773_H -#define __CROS_EC_BQ24773_H - -/* for i2c_read and i2c_write functions. */ -#include "i2c.h" - -/* I2C address */ -#define BQ24770_ADDR_FLAGS 0x09 -#define BQ24773_ADDR_FLAGS 0x6a - -/* Chip specific commands */ -#define BQ24770_CHARGE_OPTION0 0x12 -#define BQ24770_CHARGE_OPTION1 0x3B -#define BQ24770_CHARGE_OPTION2 0x38 -#define BQ24770_PROCHOT_OPTION0 0x3C -#define BQ24770_PROCHOT_OPTION1 0x3D -#define BQ24770_CHARGE_CURRENT 0x14 -#define BQ24770_MAX_CHARGE_VOLTAGE 0x15 -#define BQ24770_MIN_SYSTEM_VOLTAGE 0x3E -#define BQ24770_INPUT_CURRENT 0x3F -#define BQ24770_MANUFACTURE_ID 0xFE -#define BQ24770_DEVICE_ADDRESS 0xFF - -#define BQ24773_CHARGE_OPTION0 0x00 -#define BQ24773_CHARGE_OPTION1 0x02 -#define BQ24773_PROCHOT_OPTION0 0x04 -#define BQ24773_PROCHOT_OPTION1 0x06 -#define BQ24773_PROCHOT_STATUS 0x08 -#define BQ24773_DEVICE_ADDRESS 0x09 -#define BQ24773_CHARGE_CURRENT 0x0A -#define BQ24773_MAX_CHARGE_VOLTAGE 0x0C -#define BQ24773_MIN_SYSTEM_VOLTAGE 0x0E -#define BQ24773_INPUT_CURRENT 0x0F -#define BQ24773_CHARGE_OPTION2 0x10 - -/* Option bits */ -#define OPTION0_CHARGE_INHIBIT BIT(0) -#define OPTION0_LEARN_ENABLE BIT(5) -#define OPTION0_SWITCHING_FREQ_MASK (3 << 8) -#define OPTION0_SWITCHING_FREQ_600KHZ (0 << 8) -#define OPTION0_SWITCHING_FREQ_800KHZ BIT(8) -#define OPTION0_SWITCHING_FREQ_1000KHZ (2 << 8) -#define OPTION0_SWITCHING_FREQ_1200KHZ (3 << 8) - -#define OPTION2_EN_EXTILIM BIT(7) - -/* Prochot Option bits */ -#define PROCHOT_OPTION1_SELECTOR_MASK 0x7f /* [6:0] PROCHOT SELECTOR */ - -/* ChargeCurrent Register - 0x14 (mA) */ -#define CHARGE_I_OFF 0 -#define CHARGE_I_MIN 128 -#define CHARGE_I_MAX 8128 -#define CHARGE_I_STEP 64 - -/* MaxChargeVoltage Register - 0x15 (mV) */ -#define CHARGE_V_MIN 1024 -#define CHARGE_V_MAX 19200 -#define CHARGE_V_STEP 16 - -/* InputCurrent Register - 0x3f (mA) */ -#define INPUT_I_MIN 128 -#define INPUT_I_MAX 8128 -#define INPUT_I_STEP 64 - -#ifdef CONFIG_CHARGER_BQ24770 - #define CHARGER_NAME "bq24770" - #define I2C_ADDR_CHARGER_FLAGS BQ24770_ADDR_FLAGS - - #define REG_CHARGE_OPTION0 BQ24770_CHARGE_OPTION0 - #define REG_CHARGE_OPTION1 BQ24770_CHARGE_OPTION1 - #define REG_CHARGE_OPTION2 BQ24770_CHARGE_OPTION2 - #define REG_PROCHOT_OPTION0 BQ24770_PROCHOT_OPTION0 - #define REG_PROCHOT_OPTION1 BQ24770_PROCHOT_OPTION1 - #define REG_CHARGE_CURRENT BQ24770_CHARGE_CURRENT - #define REG_MAX_CHARGE_VOLTAGE BQ24770_MAX_CHARGE_VOLTAGE - #define REG_MIN_SYSTEM_VOLTAGE BQ24770_MIN_SYSTEM_VOLTAGE - #define REG_INPUT_CURRENT BQ24770_INPUT_CURRENT - #define REG_MANUFACTURE_ID BQ24770_MANUFACTURE_ID - #define REG_DEVICE_ADDRESS BQ24770_DEVICE_ADDRESS - -#elif defined(CONFIG_CHARGER_BQ24773) - #define CHARGER_NAME "bq24773" - #define I2C_ADDR_CHARGER_FLAGS BQ24773_ADDR_FLAGS - - #define REG_CHARGE_OPTION0 BQ24773_CHARGE_OPTION0 - #define REG_CHARGE_OPTION1 BQ24773_CHARGE_OPTION1 - #define REG_CHARGE_OPTION2 BQ24773_CHARGE_OPTION2 - #define REG_PROCHOT_OPTION0 BQ24773_PROCHOT_OPTION0 - #define REG_PROCHOT_OPTION1 BQ24773_PROCHOT_OPTION1 - #define REG_CHARGE_CURRENT BQ24773_CHARGE_CURRENT - #define REG_MAX_CHARGE_VOLTAGE BQ24773_MAX_CHARGE_VOLTAGE - #define REG_MIN_SYSTEM_VOLTAGE BQ24773_MIN_SYSTEM_VOLTAGE - #define REG_INPUT_CURRENT BQ24773_INPUT_CURRENT - #define REG_DEVICE_ADDRESS BQ24773_DEVICE_ADDRESS -#endif - -#ifdef CONFIG_CHARGER_BQ24773 -static inline int raw_read8(int offset, int *value) -{ - return i2c_read8(I2C_PORT_CHARGER, I2C_ADDR_CHARGER_FLAGS, - offset, value); -} - -static inline int raw_write8(int offset, int value) -{ - return i2c_write8(I2C_PORT_CHARGER, I2C_ADDR_CHARGER_FLAGS, - offset, value); -} -#endif - -static inline int raw_read16(int offset, int *value) -{ - return i2c_read16(I2C_PORT_CHARGER, I2C_ADDR_CHARGER_FLAGS, - offset, value); -} - -static inline int raw_write16(int offset, int value) -{ - return i2c_write16(I2C_PORT_CHARGER, I2C_ADDR_CHARGER_FLAGS, - offset, value); -} - -#endif /* __CROS_EC_BQ24773_H */ diff --git a/driver/charger/bq25703.c b/driver/charger/bq25703.c deleted file mode 100644 index 4d9fd2edcd..0000000000 --- a/driver/charger/bq25703.c +++ /dev/null @@ -1,388 +0,0 @@ -/* Copyright 2018 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. - * - * TI bq25703 battery charger driver. - */ - -#include "battery_smart.h" -#include "bq25703.h" -#include "charge_ramp.h" -#include "charger.h" -#include "common.h" -#include "console.h" -#include "hooks.h" -#include "i2c.h" -#include "timer.h" - -/* Sense resistor configurations and macros */ -#define DEFAULT_SENSE_RESISTOR 10 - -#define INPUT_RESISTOR_RATIO \ - ((CONFIG_CHARGER_SENSE_RESISTOR_AC) / DEFAULT_SENSE_RESISTOR) -#define REG_TO_INPUT_CURRENT(REG) ((REG + 1) * 50 / INPUT_RESISTOR_RATIO) -#define INPUT_CURRENT_TO_REG(CUR) (((CUR) * INPUT_RESISTOR_RATIO / 50) - 1) - -#define CHARGING_RESISTOR_RATIO \ - ((CONFIG_CHARGER_SENSE_RESISTOR) / DEFAULT_SENSE_RESISTOR) -#define REG_TO_CHARGING_CURRENT(REG) ((REG) / CHARGING_RESISTOR_RATIO) -#define CHARGING_CURRENT_TO_REG(CUR) ((CUR) * CHARGING_RESISTOR_RATIO) - - -/* Console output macros */ -#define CPRINTF(format, args...) cprintf(CC_CHARGER, format, ## args) - -/* Charger parameters */ -static const struct charger_info bq25703_charger_info = { - .name = "bq25703", - .voltage_max = 19200, - .voltage_min = 1024, - .voltage_step = 16, - .current_max = 8128 / CHARGING_RESISTOR_RATIO, - .current_min = 64 / CHARGING_RESISTOR_RATIO, - .current_step = 64 / CHARGING_RESISTOR_RATIO, - .input_current_max = 6400 / INPUT_RESISTOR_RATIO, - .input_current_min = 50 / INPUT_RESISTOR_RATIO, - .input_current_step = 50 / INPUT_RESISTOR_RATIO, -}; - -static inline int raw_read8(int offset, int *value) -{ - return i2c_read8(I2C_PORT_CHARGER, BQ25703_I2C_ADDR1, offset, value); -} - -static inline int raw_write8(int offset, int value) -{ - return i2c_write8(I2C_PORT_CHARGER, BQ25703_I2C_ADDR1, offset, value); -} - -static inline int raw_read16(int offset, int *value) -{ - return i2c_read16(I2C_PORT_CHARGER, BQ25703_I2C_ADDR1, offset, value); -} - -static inline int raw_write16(int offset, int value) -{ - return i2c_write16(I2C_PORT_CHARGER, BQ25703_I2C_ADDR1, offset, value); -} - -#ifdef CONFIG_CHARGE_RAMP_HW -static int bq25703_get_low_power_mode(int *mode) -{ - int rv; - int reg; - - rv = raw_read16(BQ25703_REG_CHARGE_OPTION_0, ®); - if (rv) - return rv; - - *mode = !!(reg & BQ25703_CHARGE_OPTION_0_LOW_POWER_MODE); - - return EC_SUCCESS; -} - -static int bq25703_set_low_power_mode(int enable) -{ - int rv; - int reg; - - rv = raw_read16(BQ25703_REG_CHARGE_OPTION_0, ®); - if (rv) - return rv; - - if (enable) - reg |= BQ25703_CHARGE_OPTION_0_LOW_POWER_MODE; - else - reg &= ~BQ25703_CHARGE_OPTION_0_LOW_POWER_MODE; - - rv = raw_write16(BQ25703_REG_CHARGE_OPTION_0, reg); - if (rv) - return rv; - - return EC_SUCCESS; -} -#endif - -/* Charger interfaces */ - -const struct charger_info *charger_get_info(void) -{ - return &bq25703_charger_info; -} - -int charger_post_init(void) -{ - /* - * Note: bq25703 power on reset state is: - * watch dog timer = 175 sec - * input current limit = ~1/2 maximum setting - * charging voltage = 0 mV - * charging current = 0 mA - * discharge on AC = disabled - */ - - /* Set charger input current limit */ - return charger_set_input_current(CONFIG_CHARGER_INPUT_CURRENT); -} - -int charger_get_status(int *status) -{ - int rv; - int option; - - rv = charger_get_option(&option); - if (rv) - return rv; - - /* Default status */ - *status = CHARGER_LEVEL_2; - - if (option & BQ25703_CHARGE_OPTION_0_CHRG_INHIBIT) - *status |= CHARGER_CHARGE_INHIBITED; - - return EC_SUCCESS; -} - -int charger_set_mode(int mode) -{ - int rv; - int option; - - rv = charger_get_option(&option); - if (rv) - return rv; - - if (mode & CHARGER_CHARGE_INHIBITED) - option |= BQ25703_CHARGE_OPTION_0_CHRG_INHIBIT; - else - option &= ~BQ25703_CHARGE_OPTION_0_CHRG_INHIBIT; - - return charger_set_option(option); -} - -int charger_enable_otg_power(int enabled) -{ - /* This is controlled with the EN_OTG pin. Support not added yet. */ - return EC_ERROR_UNIMPLEMENTED; -} - -int charger_set_otg_current_voltage(int output_current, int output_voltage) -{ - /* Add when needed. */ - return EC_ERROR_UNIMPLEMENTED; -} - -int charger_is_sourcing_otg_power(int port) -{ - /* Add when needed. */ - return EC_ERROR_UNIMPLEMENTED; -} - -int charger_get_current(int *current) -{ - int rv, reg; - - rv = raw_read16(BQ25703_REG_CHARGE_CURRENT, ®); - if (!rv) - *current = REG_TO_CHARGING_CURRENT(reg); - - return rv; -} - -int charger_set_current(int current) -{ - return raw_write16(BQ25703_REG_CHARGE_CURRENT, - CHARGING_CURRENT_TO_REG(current)); -} - -/* Get/set charge voltage limit in mV */ -int charger_get_voltage(int *voltage) -{ - return raw_read16(BQ25703_REG_MAX_CHARGE_VOLTAGE, voltage); -} -int charger_set_voltage(int voltage) -{ - return raw_write16(BQ25703_REG_MAX_CHARGE_VOLTAGE, voltage); -} - -/* Discharge battery when on AC power. */ -int charger_discharge_on_ac(int enable) -{ - int rv, option; - - rv = charger_get_option(&option); - if (rv) - return rv; - - if (enable) - option |= BQ25703_CHARGE_OPTION_0_EN_LEARN; - else - option &= ~BQ25703_CHARGE_OPTION_0_EN_LEARN; - - return charger_set_option(option); -} - -int charger_set_input_current(int input_current) -{ - return raw_write8(BQ25703_REG_IIN_HOST, - INPUT_CURRENT_TO_REG(input_current)); -} - -int charger_get_input_current(int *input_current) -{ - int rv, reg; - - /* - * IIN_DPM register reflects the actual input current limit programmed - * in the register, either from host or from ICO. After ICO, the - * current limit used by DPM regulation may differ from the IIN_HOST - * register settings. - */ - rv = raw_read8(BQ25703_REG_IIN_DPM, ®); - if (!rv) - *input_current = REG_TO_INPUT_CURRENT(reg); - - return rv; -} - -int charger_manufacturer_id(int *id) -{ - return raw_read8(BQ25703_REG_MANUFACTURER_ID, id); -} -int charger_device_id(int *id) -{ - return raw_read8(BQ25703_REG_DEVICE_ADDRESS, id); -} - -int charger_get_option(int *option) -{ - /* There are 4 option registers, but we only need the first for now. */ - return raw_read16(BQ25703_REG_CHARGE_OPTION_0, option); -} - -int charger_set_option(int option) -{ - /* There are 4 option registers, but we only need the first for now. */ - return raw_write16(BQ25703_REG_CHARGE_OPTION_0, option); -} - -#ifdef CONFIG_CHARGE_RAMP_HW - -static void bq25703_chg_ramp_handle(void) -{ - int ramp_curr; - - /* - * Once the charge ramp is stable write back the stable ramp - * current to input current register. - */ - if (chg_ramp_is_stable()) { - ramp_curr = chg_ramp_get_current_limit(); - if (ramp_curr && !charger_set_input_current(ramp_curr)) - CPRINTF("stable ramp current=%d\n", ramp_curr); - } -} -DECLARE_DEFERRED(bq25703_chg_ramp_handle); - -int charger_set_hw_ramp(int enable) -{ - int option3_reg, option2_reg, rv; - - rv = raw_read16(BQ25703_REG_CHARGE_OPTION_3, &option3_reg); - if (rv) - return rv; - rv = raw_read16(BQ25703_REG_CHARGE_OPTION_2, &option2_reg); - if (rv) - return rv; - - if (enable) { - /* Set InputVoltage register to BC1.2 minimum ramp voltage */ - rv = raw_write16(BQ25703_REG_INPUT_VOLTAGE, - BQ25703_BC12_MIN_VOLTAGE_MV); - if (rv) - return rv; - - /* Enable ICO algorithm */ - option3_reg |= BQ25703_CHARGE_OPTION_3_EN_ICO_MODE; - - /* 0b: Input current limit is set by BQ25703_REG_IIN_HOST */ - option2_reg &= ~BQ25703_CHARGE_OPTION_2_EN_EXTILIM; - - /* Charge ramp may take up to 2s to settle down */ - hook_call_deferred(&bq25703_chg_ramp_handle_data, (4 * SECOND)); - } else { - /* Disable ICO algorithm */ - option3_reg &= ~BQ25703_CHARGE_OPTION_3_EN_ICO_MODE; - - /* - * 1b: Input current limit is set by the lower value of - * ILIM_HIZ pin and BQ25703_REG_IIN_HOST - */ - option2_reg |= BQ25703_CHARGE_OPTION_2_EN_EXTILIM; - } - - rv = raw_write16(BQ25703_REG_CHARGE_OPTION_2, option2_reg); - if (rv) - return rv; - return raw_write16(BQ25703_REG_CHARGE_OPTION_3, option3_reg); -} - -int chg_ramp_is_stable(void) -{ - int reg; - - if (raw_read16(BQ25703_REG_CHARGER_STATUS, ®)) - return 0; - - return reg & BQ25703_CHARGE_STATUS_ICO_DONE; -} - -int chg_ramp_get_current_limit(void) -{ - int reg; - int mode; - int tries_left = 8; - - /* Save current mode to restore same state after ADC read */ - if (bq25703_get_low_power_mode(&mode)) - goto error; - - /* Exit low power mode so ADC conversion takes typical time */ - if (bq25703_set_low_power_mode(0)) - goto error; - - /* Turn on the ADC for one reading */ - reg = BQ25703_ADC_OPTION_ADC_START | BQ25703_ADC_OPTION_EN_ADC_IIN; - if (raw_write16(BQ25703_REG_ADC_OPTION, reg)) - goto error; - - /* - * Wait until the ADC operation completes. The spec says typical - * conversion time is 10 msec. If low power mode isn't exited first, - * then the conversion time jumps to ~60 msec. - */ - do { - msleep(2); - raw_read16(BQ25703_REG_ADC_OPTION, ®); - } while (--tries_left && (reg & BQ25703_ADC_OPTION_ADC_START)); - - /* ADC reading attempt complete, go back to low power mode */ - if (bq25703_set_low_power_mode(mode)) - goto error; - - /* Could not complete read */ - if (reg & BQ25703_ADC_OPTION_ADC_START) - goto error; - - /* Read ADC value */ - if (raw_read8(BQ25703_REG_ADC_IIN, ®)) - goto error; - - /* LSB => 50mA */ - return reg * BQ25703_ADC_IIN_STEP_MA; - -error: - CPRINTF("Could not read input current limit ADC!\n"); - return 0; -} -#endif /* CONFIG_CHARGE_RAMP_HW */ diff --git a/driver/charger/bq25703.h b/driver/charger/bq25703.h deleted file mode 100644 index f715824f63..0000000000 --- a/driver/charger/bq25703.h +++ /dev/null @@ -1,75 +0,0 @@ -/* Copyright 2018 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. - * - * TI bq25703 battery charger driver. - */ - -#ifndef __CROS_EC_BQ25703_H -#define __CROS_EC_BQ25703_H - -/* I2C Interface */ -#define BQ25703_I2C_ADDR1_FLAGS 0x6B - -/* - * BC1.2 minimum voltage threshold for BQ25703. - * BC1.2 charging port output voltage range is 4.75V to 5.25V, - * BQ25703 Input Voltage Accuracy is -2% to +2% (-95mV to +95mV) - * 4750mV - 95mV => 4655mV - 3200 (offset reg 0x0A) => 1455mv - * 1455mv & 0x1FC0 = 1408 (data for register 0x0A) - */ -#define BQ25703_BC12_MIN_VOLTAGE_MV 1408 - -/* Registers */ - -/* ChargeOption0 Register */ -#define BQ25703_REG_CHARGE_OPTION_0 0x00 -#define BQ25703_CHARGE_OPTION_0_LOW_POWER_MODE BIT(15) -#define BQ25703_CHARGE_OPTION_0_EN_LEARN BIT(5) -#define BQ25703_CHARGE_OPTION_0_CHRG_INHIBIT BIT(0) - -#define BQ25703_REG_CHARGE_CURRENT 0x02 -#define BQ25703_REG_MAX_CHARGE_VOLTAGE 0x04 -#define BQ25703_REG_CHARGE_OPTION_1 0x30 - -/* ChargeOption2 Register */ -#define BQ25703_REG_CHARGE_OPTION_2 0x32 -#define BQ25703_CHARGE_OPTION_2_EN_EXTILIM BIT(7) - -/* ChargeOption3 Register */ -#define BQ25703_REG_CHARGE_OPTION_3 0x34 -#define BQ25703_CHARGE_OPTION_3_EN_ICO_MODE BIT(11) - -#define BQ25703_REG_PROCHOT_OPTION_0 0x36 -#define BQ25703_REG_PROCHOT_OPTION_1 0x38 - -/* ADCOption Register */ -#define BQ25703_REG_ADC_OPTION 0x3A -#define BQ25703_ADC_OPTION_ADC_START BIT(14) -#define BQ25703_ADC_OPTION_EN_ADC_IIN BIT(4) - -/* ChargeStatus Register */ -#define BQ25703_REG_CHARGER_STATUS 0x20 -#define BQ25703_CHARGE_STATUS_ICO_DONE BIT(14) - -#define BQ25703_REG_PROCHOT_STATUS 0x22 -#define BQ25703_REG_IIN_DPM 0x25 -#define BQ25703_REG_ADC_PSYS 0x26 -#define BQ25703_REG_ADC_VBUS 0x27 -#define BQ25703_REG_ADC_IBAT 0x28 -#define BQ25703_REG_ADC_CMPIN 0x2A - -/* ADCIIN Register */ -#define BQ25703_REG_ADC_IIN 0x2B -#define BQ25703_ADC_IIN_STEP_MA 50 - -#define BQ25703_REG_ADC_VSYS_VBAT 0x2C -#define BQ25703_REG_OTG_VOLTAGE 0x06 -#define BQ25703_REG_OTG_CURRENT 0x08 -#define BQ25703_REG_INPUT_VOLTAGE 0x0A -#define BQ25703_REG_MIN_SYSTEM_VOLTAGE 0x0C -#define BQ25703_REG_IIN_HOST 0x0F -#define BQ25703_REG_MANUFACTURER_ID 0x2E -#define BQ25703_REG_DEVICE_ADDRESS 0x2F - -#endif /* __CROS_EC_BQ25703_H */ diff --git a/driver/charger/bq25710.c b/driver/charger/bq25710.c deleted file mode 100644 index 8e418ea103..0000000000 --- a/driver/charger/bq25710.c +++ /dev/null @@ -1,608 +0,0 @@ -/* Copyright 2018 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. - * - * TI bq25710 battery charger driver. - */ - -#include "battery.h" -#include "battery_smart.h" -#include "bq25710.h" -#include "charge_ramp.h" -#include "charger.h" -#include "common.h" -#include "console.h" -#include "hooks.h" -#include "i2c.h" -#include "task.h" -#include "timer.h" - -#ifndef CONFIG_CHARGER_NARROW_VDC -#error "BQ25710 is a NVDC charger, please enable CONFIG_CHARGER_NARROW_VDC." -#endif - -/* Sense resistor configurations and macros */ -#define DEFAULT_SENSE_RESISTOR 10 - -#define INPUT_RESISTOR_RATIO \ - ((CONFIG_CHARGER_SENSE_RESISTOR_AC) / DEFAULT_SENSE_RESISTOR) -#define REG_TO_INPUT_CURRENT(REG) ((REG + 1) * 50 / INPUT_RESISTOR_RATIO) -#define INPUT_CURRENT_TO_REG(CUR) (((CUR) * INPUT_RESISTOR_RATIO / 50) - 1) - -#define CHARGING_RESISTOR_RATIO \ - ((CONFIG_CHARGER_SENSE_RESISTOR) / DEFAULT_SENSE_RESISTOR) -#define REG_TO_CHARGING_CURRENT(REG) ((REG) / CHARGING_RESISTOR_RATIO) -#define CHARGING_CURRENT_TO_REG(CUR) ((CUR) * CHARGING_RESISTOR_RATIO) - -/* Console output macros */ -#define CPRINTF(format, args...) cprintf(CC_CHARGER, format, ## args) - -#ifdef CONFIG_CHARGER_BQ25710_IDCHG_LIMIT_MA -/* - * If this config option is defined, then the bq25710 needs to remain in - * performance mode when the AP is in S0. Performance mode is active whenever AC - * power is connected or when the EN_LWPWR bit in ChargeOption0 is clear. - */ -static uint32_t bq25710_perf_mode_req; -static struct mutex bq25710_perf_mode_mutex; -#endif - -/* Charger parameters */ -static const struct charger_info bq25710_charger_info = { - .name = "bq25710", - .voltage_max = 19200, - .voltage_min = 1024, - .voltage_step = 16, - .current_max = 8128 / CHARGING_RESISTOR_RATIO, - .current_min = 64 / CHARGING_RESISTOR_RATIO, - .current_step = 64 / CHARGING_RESISTOR_RATIO, - .input_current_max = 6400 / INPUT_RESISTOR_RATIO, - .input_current_min = 50 / INPUT_RESISTOR_RATIO, - .input_current_step = 50 / INPUT_RESISTOR_RATIO, -}; - -static inline int raw_read16(int offset, int *value) -{ - return i2c_read16(I2C_PORT_CHARGER, BQ25710_SMBUS_ADDR1_FLAGS, - offset, value); -} - -static inline int raw_write16(int offset, int value) -{ - return i2c_write16(I2C_PORT_CHARGER, BQ25710_SMBUS_ADDR1_FLAGS, - offset, value); -} - -#if defined(CONFIG_CHARGE_RAMP_HW) || \ - defined(CONFIG_USB_PD_VBUS_MEASURE_CHARGER) -static int bq25710_get_low_power_mode(int *mode) -{ - int rv; - int reg; - - rv = raw_read16(BQ25710_REG_CHARGE_OPTION_0, ®); - if (rv) - return rv; - - *mode = !!(reg & BQ25710_CHARGE_OPTION_0_LOW_POWER_MODE); - - return EC_SUCCESS; -} - -static int bq25710_set_low_power_mode(int enable) -{ - int rv; - int reg; - - rv = raw_read16(BQ25710_REG_CHARGE_OPTION_0, ®); - if (rv) - return rv; - -#ifdef CONFIG_CHARGER_BQ25710_IDCHG_LIMIT_MA - mutex_lock(&bq25710_perf_mode_mutex); - /* - * Performance mode means not in low power mode. The bit that controls - * this is EN_LWPWR in ChargeOption0. The 'enable' param in this - * function is refeerring to low power mode, so enabling low power mode - * means disabling performance mode and vice versa. - */ - if (enable) - bq25710_perf_mode_req &= ~(1 << task_get_current()); - else - bq25710_perf_mode_req |= (1 << task_get_current()); - enable = !bq25710_perf_mode_req; -#endif - - if (enable) - reg |= BQ25710_CHARGE_OPTION_0_LOW_POWER_MODE; - else - reg &= ~BQ25710_CHARGE_OPTION_0_LOW_POWER_MODE; - - rv = raw_write16(BQ25710_REG_CHARGE_OPTION_0, reg); -#ifdef CONFIG_CHARGER_BQ25710_IDCHG_LIMIT_MA - mutex_unlock(&bq25710_perf_mode_mutex); -#endif - if (rv) - return rv; - - return EC_SUCCESS; -} - -static int bq25710_adc_start(int adc_en_mask) -{ - int reg; - int mode; - int tries_left = 8; - - /* Save current mode to restore same state after ADC read */ - if (bq25710_get_low_power_mode(&mode)) - return EC_ERROR_UNKNOWN; - - /* Exit low power mode so ADC conversion takes typical time */ - if (bq25710_set_low_power_mode(0)) - return EC_ERROR_UNKNOWN; - - /* - * Turn on the ADC for one reading. Note that adc_en_mask - * maps to bit[7:0] in ADCOption register. - */ - reg = (adc_en_mask & BQ25710_ADC_OPTION_EN_ADC_ALL) | - BQ25710_ADC_OPTION_ADC_START; - if (raw_write16(BQ25710_REG_ADC_OPTION, reg)) - return EC_ERROR_UNKNOWN; - - /* - * Wait until the ADC operation completes. The spec says typical - * conversion time is 10 msec. If low power mode isn't exited first, - * then the conversion time jumps to ~60 msec. - */ - do { - msleep(2); - raw_read16(BQ25710_REG_ADC_OPTION, ®); - } while (--tries_left && (reg & BQ25710_ADC_OPTION_ADC_START)); - - /* ADC reading attempt complete, go back to low power mode */ - if (bq25710_set_low_power_mode(mode)) - return EC_ERROR_UNKNOWN; - - /* Could not complete read */ - if (reg & BQ25710_ADC_OPTION_ADC_START) - return EC_ERROR_TIMEOUT; - - return EC_SUCCESS; -} -#endif - -static void bq25710_init(void) -{ - int reg; - int vsys; - int rv; - - /* - * Reset registers to their default settings. There is no reset pin for - * this chip so without a full power cycle, some registers may not be at - * their default values. Note, need to save the POR value of - * MIN_SYSTEM_VOLTAGE register prior to setting the reset so that the - * correct value is preserved. - */ - rv = raw_read16(BQ25710_REG_MIN_SYSTEM_VOLTAGE, &vsys); - rv |= raw_read16(BQ25710_REG_CHARGE_OPTION_3, ®); - if (!rv) { - reg |= BQ25710_CHARGE_OPTION_3_RESET_REG; - /* Set all registers to default values */ - raw_write16(BQ25710_REG_CHARGE_OPTION_3, reg); - /* Restore VSYS_MIN voltage to POR reset value */ - raw_write16(BQ25710_REG_MIN_SYSTEM_VOLTAGE, vsys); - } - - if (!raw_read16(BQ25710_REG_PROCHOT_OPTION_1, ®)) { - /* Disbale VDPM prochot profile at initialization */ - reg &= ~BQ25710_PROCHOT_PROFILE_VDPM; - /* - * Enable PROCHOT to be asserted with VSYS min detection. Note - * that when no battery is present, then VSYS will be set to the - * value in register 0x3E (MinSysVoltage) which means that when - * no battery is present prochot will continuosly be asserted. - */ - reg |= BQ25710_PROCHOT_PROFILE_VSYS; -#ifdef CONFIG_CHARGER_BQ25710_IDCHG_LIMIT_MA - /* - * Set the IDCHG limit who's value is defined in the config - * option in mA. Also, enable IDCHG trigger for prochot. - */ - reg &= ~BQ25710_PROCHOT_IDCHG_VTH_MASK; - /* - * IDCHG limit is in 512 mA steps. Note there is a 128 mA offset - * so the actual IDCHG limit will be the value stored in bits - * 15:10 + 128 mA. - */ - reg |= ((CONFIG_CHARGER_BQ25710_IDCHG_LIMIT_MA << 1) & - BQ25710_PROCHOT_IDCHG_VTH_MASK); - reg |= BQ25710_PROCHOT_PROFILE_IDCHG; -#endif - raw_write16(BQ25710_REG_PROCHOT_OPTION_1, reg); - } - - /* Reduce ILIM from default of 150% to 105% */ - if (!raw_read16(BQ25710_REG_PROCHOT_OPTION_0, ®)) { - reg &= ~BQ25710_PROCHOT0_ILIM_VTH_MASK; - raw_write16(BQ25710_REG_PROCHOT_OPTION_0, reg); - } - - /* - * Reduce peak power mode overload and relax cycle time from default 20 - * msec to the minimum of 5 msec. - */ - if (!raw_read16(BQ25710_REG_CHARGE_OPTION_2, ®)) { - reg &= ~BQ25710_CHARGE_OPTION_2_TMAX_MASK; - raw_write16(BQ25710_REG_CHARGE_OPTION_2, reg); - } -} -DECLARE_HOOK(HOOK_INIT, bq25710_init, HOOK_PRIO_INIT_I2C + 1); - -/* Charger interfaces */ -const struct charger_info *charger_get_info(void) -{ - return &bq25710_charger_info; -} - -int charger_post_init(void) -{ - /* - * Note: bq25710 power on reset state is: - * watch dog timer = 175 sec - * input current limit = ~1/2 maximum setting - * charging voltage = 0 mV - * charging current = 0 mA - * discharge on AC = disabled - */ - - return EC_SUCCESS; -} - -int charger_get_status(int *status) -{ - int rv; - int option; - - rv = charger_get_option(&option); - if (rv) - return rv; - - /* Default status */ - *status = CHARGER_LEVEL_2; - - if (option & BQ25710_CHARGE_OPTION_0_CHRG_INHIBIT) - *status |= CHARGER_CHARGE_INHIBITED; - - return EC_SUCCESS; -} - -int charger_set_mode(int mode) -{ - int rv; - int option; - - rv = charger_get_option(&option); - if (rv) - return rv; - - if (mode & CHARGER_CHARGE_INHIBITED) - option |= BQ25710_CHARGE_OPTION_0_CHRG_INHIBIT; - else - option &= ~BQ25710_CHARGE_OPTION_0_CHRG_INHIBIT; - - return charger_set_option(option); -} - -int charger_enable_otg_power(int enabled) -{ - /* This is controlled with the EN_OTG pin. Support not added yet. */ - return EC_ERROR_UNIMPLEMENTED; -} - -int charger_set_otg_current_voltage(int output_current, int output_voltage) -{ - /* Add when needed. */ - return EC_ERROR_UNIMPLEMENTED; -} - -int charger_is_sourcing_otg_power(int port) -{ - /* Add when needed. */ - return EC_ERROR_UNIMPLEMENTED; -} - -int charger_get_current(int *current) -{ - int rv, reg; - - rv = raw_read16(BQ25710_REG_CHARGE_CURRENT, ®); - if (!rv) - *current = REG_TO_CHARGING_CURRENT(reg); - - return rv; -} - -int charger_set_current(int current) -{ - return raw_write16(BQ25710_REG_CHARGE_CURRENT, - CHARGING_CURRENT_TO_REG(current)); -} - -/* Get/set charge voltage limit in mV */ -int charger_get_voltage(int *voltage) -{ - return raw_read16(BQ25710_REG_MAX_CHARGE_VOLTAGE, voltage); -} - -int charger_set_voltage(int voltage) -{ - return raw_write16(BQ25710_REG_MAX_CHARGE_VOLTAGE, voltage); -} - -/* Discharge battery when on AC power. */ -int charger_discharge_on_ac(int enable) -{ - int rv, option; - - rv = charger_get_option(&option); - if (rv) - return rv; - - if (enable) - option |= BQ25710_CHARGE_OPTION_0_EN_LEARN; - else - option &= ~BQ25710_CHARGE_OPTION_0_EN_LEARN; - - return charger_set_option(option); -} - -int charger_set_input_current(int input_current) -{ - int num_steps = INPUT_CURRENT_TO_REG(input_current); - - return raw_write16(BQ25710_REG_IIN_HOST, num_steps << - BQ25710_CHARGE_IIN_BIT_0FFSET); -} - -int charger_get_input_current(int *input_current) -{ - int rv, reg; - - /* - * IIN_DPM register reflects the actual input current limit programmed - * in the register, either from host or from ICO. After ICO, the - * current limit used by DPM regulation may differ from the IIN_HOST - * register settings. - */ - rv = raw_read16(BQ25710_REG_IIN_DPM, ®); - if (!rv) - *input_current = - REG_TO_INPUT_CURRENT((reg >> - BQ25710_CHARGE_IIN_BIT_0FFSET)); - - return rv; -} - -int charger_manufacturer_id(int *id) -{ - return raw_read16(BQ25710_REG_MANUFACTURER_ID, id); -} - -int charger_device_id(int *id) -{ - return raw_read16(BQ25710_REG_DEVICE_ADDRESS, id); -} - -#ifdef CONFIG_USB_PD_VBUS_MEASURE_CHARGER -int charger_get_vbus_voltage(int port) -{ - int reg, rv; - - rv = bq25710_adc_start(BQ25710_ADC_OPTION_EN_ADC_VBUS); - if (rv) - goto error; - - /* Read ADC value */ - rv = raw_read16(BQ25710_REG_ADC_VBUS_PSYS, ®); - if (rv) - goto error; - - reg >>= BQ25710_ADC_VBUS_STEP_BIT_OFFSET; - /* - * LSB => 64mV. - * Return 0 when VBUS <= 3.2V as ADC can't measure it. - */ - return reg ? - (reg * BQ25710_ADC_VBUS_STEP_MV + BQ25710_ADC_VBUS_BASE_MV) : 0; - -error: - CPRINTF("Could not read VBUS ADC! Error: %d\n", rv); - return 0; -} -#endif - -int charger_get_option(int *option) -{ - /* There are 4 option registers, but we only need the first for now. */ - return raw_read16(BQ25710_REG_CHARGE_OPTION_0, option); -} - -int charger_set_option(int option) -{ - /* There are 4 option registers, but we only need the first for now. */ - return raw_write16(BQ25710_REG_CHARGE_OPTION_0, option); -} - -#ifdef CONFIG_CHARGE_RAMP_HW - -static void bq25710_chg_ramp_handle(void) -{ - int ramp_curr; - - /* - * Once the charge ramp is stable write back the stable ramp - * current to the host input current limit register - */ - ramp_curr = chg_ramp_get_current_limit(); - if (chg_ramp_is_stable()) { - if (ramp_curr && !charger_set_input_current(ramp_curr)) - CPRINTF("bq25710: stable ramp current=%d\n", ramp_curr); - } else { - CPRINTF("bq25710: ICO stall, ramp current=%d\n", ramp_curr); - } - /* - * Disable ICO mode. When ICO mode is active the input current limit is - * given by the value in register IIN_DPM (0x22) - */ - charger_set_hw_ramp(0); -} -DECLARE_DEFERRED(bq25710_chg_ramp_handle); - -int charger_set_hw_ramp(int enable) -{ - int option3_reg, option2_reg, rv; - - rv = raw_read16(BQ25710_REG_CHARGE_OPTION_3, &option3_reg); - if (rv) - return rv; - rv = raw_read16(BQ25710_REG_CHARGE_OPTION_2, &option2_reg); - if (rv) - return rv; - - if (enable) { - /* - * ICO mode can only be used when a battery is present. If there - * is no battery, then enabling ICO mode will lead to VSYS - * dropping out. - */ - if (!battery_is_present()) { - CPRINTF("bq25710: no battery, skip ICO enable\n"); - return EC_ERROR_UNKNOWN; - } - - /* Set InputVoltage register to BC1.2 minimum ramp voltage */ - rv = raw_write16(BQ25710_REG_INPUT_VOLTAGE, - BQ25710_BC12_MIN_VOLTAGE_MV); - if (rv) - return rv; - - /* Enable ICO algorithm */ - option3_reg |= BQ25710_CHARGE_OPTION_3_EN_ICO_MODE; - - /* 0b: Input current limit is set by BQ25710_REG_IIN_HOST */ - option2_reg &= ~BQ25710_CHARGE_OPTION_2_EN_EXTILIM; - - /* Charge ramp may take up to 2s to settle down */ - hook_call_deferred(&bq25710_chg_ramp_handle_data, (4 * SECOND)); - } else { - /* Disable ICO algorithm */ - option3_reg &= ~BQ25710_CHARGE_OPTION_3_EN_ICO_MODE; - - /* - * 1b: Input current limit is set by the lower value of - * ILIM_HIZ pin and BQ25710_REG_IIN_HOST - */ - option2_reg |= BQ25710_CHARGE_OPTION_2_EN_EXTILIM; - } - - rv = raw_write16(BQ25710_REG_CHARGE_OPTION_2, option2_reg); - if (rv) - return rv; - return raw_write16(BQ25710_REG_CHARGE_OPTION_3, option3_reg); -} - -int chg_ramp_is_stable(void) -{ - int reg; - - if (raw_read16(BQ25710_REG_CHARGER_STATUS, ®)) - return 0; - - return reg & BQ25710_CHARGE_STATUS_ICO_DONE; -} - -int chg_ramp_get_current_limit(void) -{ - int reg, rv; - - rv = raw_read16(BQ25710_REG_IIN_DPM, ®); - if (rv) { - CPRINTF("Could not read iin_dpm current limit! Error: %d\n", - rv); - return 0; - } - - return ((reg >> BQ25710_IIN_DPM_BIT_SHIFT) * BQ25710_IIN_DPM_STEP_MA + - BQ25710_IIN_DPM_STEP_MA); -} -#endif /* CONFIG_CHARGE_RAMP_HW */ - -#ifdef CONFIG_CHARGER_BQ25710_IDCHG_LIMIT_MA -/* Called on AP S5 -> S3 and S3/S0iX -> S0 transition */ -static void bq25710_chipset_startup(void) -{ - bq25710_set_low_power_mode(0); -} -DECLARE_HOOK(HOOK_CHIPSET_STARTUP, bq25710_chipset_startup, HOOK_PRIO_DEFAULT); -DECLARE_HOOK(HOOK_CHIPSET_RESUME, bq25710_chipset_startup, HOOK_PRIO_DEFAULT); - - -/* Called on AP S0 -> S0iX/S3 or S3 -> S5 transition */ -static void bq25710_chipset_suspend(void) -{ - bq25710_set_low_power_mode(1); -} -DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, bq25710_chipset_suspend, HOOK_PRIO_DEFAULT); -DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, bq25710_chipset_suspend, HOOK_PRIO_DEFAULT); -#endif - -#ifdef CONFIG_CMD_CHARGER_DUMP -static int console_bq25710_dump_regs(int argc, char **argv) -{ - int i; - int val; - - /* Dump all readable registers on bq25710. */ - static const uint8_t regs[] = { - BQ25710_REG_CHARGE_OPTION_0, - BQ25710_REG_CHARGE_CURRENT, - BQ25710_REG_MAX_CHARGE_VOLTAGE, - BQ25710_REG_CHARGE_OPTION_1, - BQ25710_REG_CHARGE_OPTION_2, - BQ25710_REG_CHARGE_OPTION_3, - BQ25710_REG_PROCHOT_OPTION_0, - BQ25710_REG_PROCHOT_OPTION_1, - BQ25710_REG_ADC_OPTION, - BQ25710_REG_CHARGER_STATUS, - BQ25710_REG_PROCHOT_STATUS, - BQ25710_REG_IIN_DPM, - BQ25710_REG_ADC_VBUS_PSYS, - BQ25710_REG_ADC_IBAT, - BQ25710_REG_ADC_CMPIN_IIN, - BQ25710_REG_ADC_VSYS_VBAT, - BQ25710_REG_PROCHOT_OPTION_1, - BQ25710_REG_OTG_VOLTAGE, - BQ25710_REG_OTG_CURRENT, - BQ25710_REG_INPUT_VOLTAGE, - BQ25710_REG_MIN_SYSTEM_VOLTAGE, - BQ25710_REG_IIN_HOST, - BQ25710_REG_MANUFACTURER_ID, - BQ25710_REG_DEVICE_ADDRESS, - }; - - for (i = 0; i < ARRAY_SIZE(regs); ++i) { - if (raw_read16(regs[i], &val)) - continue; - ccprintf("BQ25710 REG 0x%02x: 0x%04x\n", regs[i], val); - } - - return 0; -} -DECLARE_CONSOLE_COMMAND(charger_dump, console_bq25710_dump_regs, - "", - "Dump all charger registers"); - -#endif /* CONFIG_CMD_CHARGER_DUMP */ diff --git a/driver/charger/bq25710.h b/driver/charger/bq25710.h deleted file mode 100644 index 014799a832..0000000000 --- a/driver/charger/bq25710.h +++ /dev/null @@ -1,96 +0,0 @@ -/* Copyright 2018 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. - * - * TI bq25710 battery charger driver. - */ - -#ifndef __CROS_EC_BQ25710_H -#define __CROS_EC_BQ25710_H - -/* SMBUS Interface */ -#define BQ25710_SMBUS_ADDR1_FLAGS 0x09 - -#define BQ25710_BC12_MIN_VOLTAGE_MV 1408 - -/* Registers */ -#define BQ25710_REG_CHARGE_OPTION_0 0x12 -#define BQ25710_REG_CHARGE_CURRENT 0x14 -#define BQ25710_REG_MAX_CHARGE_VOLTAGE 0x15 -#define BQ25710_REG_CHARGE_OPTION_1 0x30 -#define BQ25710_REG_CHARGE_OPTION_2 0x31 -#define BQ25710_REG_CHARGE_OPTION_3 0x32 -#define BQ25710_REG_PROCHOT_OPTION_0 0x33 -#define BQ25710_REG_PROCHOT_OPTION_1 0x34 -#define BQ25710_REG_ADC_OPTION 0x35 -#define BQ25710_REG_CHARGER_STATUS 0x20 -#define BQ25710_REG_PROCHOT_STATUS 0x21 -#define BQ25710_REG_IIN_DPM 0x22 -#define BQ25710_REG_ADC_VBUS_PSYS 0x23 -#define BQ25710_REG_ADC_IBAT 0x24 -#define BQ25710_REG_ADC_CMPIN_IIN 0x25 -#define BQ25710_REG_ADC_VSYS_VBAT 0x2C -#define BQ25710_REG_PROCHOT_OPTION_1 0x34 -#define BQ25710_REG_OTG_VOLTAGE 0x3B -#define BQ25710_REG_OTG_CURRENT 0x3C -#define BQ25710_REG_INPUT_VOLTAGE 0x3D -#define BQ25710_REG_MIN_SYSTEM_VOLTAGE 0x3E -#define BQ25710_REG_IIN_HOST 0x3F -#define BQ25710_REG_MANUFACTURER_ID 0xFE -#define BQ25710_REG_DEVICE_ADDRESS 0xFF - -/* ChargeOption0 Register */ -#define BQ25710_CHARGE_OPTION_0_LOW_POWER_MODE BIT(15) -#define BQ25710_CHARGE_OPTION_0_IDPM_AUTO_DIS BIT(12) -#define BQ25710_CHARGE_OPTION_0_EN_LEARN BIT(5) -#define BQ25710_CHARGE_OPTION_0_EN_IDPM BIT(1) -#define BQ25710_CHARGE_OPTION_0_CHRG_INHIBIT BIT(0) - -/* ChargeOption2 Register */ -#define BQ25710_CHARGE_OPTION_2_EN_EXTILIM BIT(7) -#define BQ25710_CHARGE_OPTION_2_TMAX_SHIFT 8 -#define BQ25710_CHARGE_OPTION_2_TMAX_MASK (0x3 << \ - BQ25710_CHARGE_OPTION_2_TMAX_SHIFT) - -/* ChargeOption3 Register */ -#define BQ25710_CHARGE_OPTION_3_RESET_REG BIT(14) -#define BQ25710_CHARGE_OPTION_3_EN_ICO_MODE BIT(11) - -/* ChargeStatus Register */ -#define BQ25710_CHARGE_STATUS_ICO_DONE BIT(14) - -/* IIN_DPM Register */ -#define BQ25710_CHARGE_IIN_BIT_0FFSET 8 -#define BQ25710_CHARGE_MA_PER_STEP 50 - -/* ADCOption Register */ -#define BQ25710_ADC_OPTION_ADC_START BIT(14) -#define BQ25710_ADC_OPTION_EN_ADC_VBUS BIT(6) -#define BQ25710_ADC_OPTION_EN_ADC_IIN BIT(4) -#define BQ25710_ADC_OPTION_EN_ADC_ALL 0xFF - -/* ADCVBUS/PSYS Register */ -#define BQ25710_ADC_VBUS_STEP_MV 64 -#define BQ25710_ADC_VBUS_BASE_MV 3200 -#define BQ25710_ADC_VBUS_STEP_BIT_OFFSET 8 - -/* ADCIIN Register */ -#define BQ25710_ADC_IIN_STEP_MA 50 -#define BQ25710_ADC_IIN_STEP_BIT_OFFSET 8 - -/* ProchotOption0 Register */ -#define BQ25710_PROCHOT0_ILIM_VTH_SHIFT 11 -#define BQ25710_PROCHOT0_ILIM_VTH_MASK (0x1f << \ - BQ25710_PROCHOT0_ILIM_VTH_SHIFT) - -/* ProchotOption1 Register */ -#define BQ25710_PROCHOT_PROFILE_VDPM BIT(7) -#define BQ25710_PROCHOT_PROFILE_IDCHG BIT(3) -#define BQ25710_PROCHOT_PROFILE_VSYS BIT(2) -#define BQ25710_PROCHOT_IDCHG_VTH_MASK 0xFC00 - -/* IIN_DPM Register */ -#define BQ25710_IIN_DPM_BIT_SHIFT 8 -#define BQ25710_IIN_DPM_STEP_MA 50 - -#endif /* __CROS_EC_BQ25710_H */ diff --git a/driver/charger/bq2589x.c b/driver/charger/bq2589x.c deleted file mode 100644 index 966a0d0016..0000000000 --- a/driver/charger/bq2589x.c +++ /dev/null @@ -1,394 +0,0 @@ -/* 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. - * - * TI bq25890/bq25892/bq25895 battery charger driver. - */ - -#include "config.h" -#include "bq2589x.h" -#include "charger.h" -#include "common.h" -#include "console.h" -#include "hooks.h" -#include "i2c.h" -#include "printf.h" -#include "util.h" - -/* Console output macros */ -#define CPUTS(outstr) cputs(CC_CHARGER, outstr) -#define CPRINTF(format, args...) cprintf(CC_CHARGER, format, ## args) - -/* 5V Boost settings */ -#ifndef CONFIG_CHARGER_BQ2589X_BOOST -#define CONFIG_CHARGER_BQ2589X_BOOST BQ2589X_BOOST_DEFAULT -#endif - -/* IR compensation settings */ -#ifndef CONFIG_CHARGER_BQ2589X_IR_COMP -#define CONFIG_CHARGER_BQ2589X_IR_COMP BQ2589X_IR_COMP_DEFAULT -#endif - -/* Termination current limit setting */ -#ifndef CONFIG_CHARGER_TERM_CURRENT_LIMIT -#define CONFIG_CHARGER_TERM_CURRENT_LIMIT BQ2589X_TERM_CURRENT_LIMIT_DEFAULT -#endif - -/* Charger information */ -static const struct charger_info bq2589x_charger_info = { - .name = "bq2589x", - .voltage_max = 4608, - .voltage_min = 3840, - .voltage_step = 16, - .current_max = 5056, - .current_min = 0, - .current_step = 64, - .input_current_max = 3250, - .input_current_min = 100, - .input_current_step = 50, -}; - -static int bq2589x_read(int reg, int *value) -{ - return i2c_read8(I2C_PORT_CHARGER, BQ2589X_ADDR, reg, value); -} - -static int bq2589x_write(int reg, int value) -{ - return i2c_write8(I2C_PORT_CHARGER, BQ2589X_ADDR, reg, value); -} - -static int bq2589x_watchdog_reset(void) -{ - int rv, val; - - rv = bq2589x_read(BQ2589X_REG_CFG2, &val); - if (rv) - return rv; - val |= BQ2589X_CFG2_WD_RST; - return bq2589x_write(BQ2589X_REG_CFG2, val); -} - -static int bq2589x_set_terminate_current(int current) -{ - int reg_val, rv; - int val = (current - 64) / 64; - - rv = bq2589x_read(BQ2589X_REG_PRE_CHG_CURR, ®_val); - if (rv) - return rv; - reg_val = (reg_val & ~0xf) | (val & 0xf); - return bq2589x_write(BQ2589X_REG_PRE_CHG_CURR, reg_val); -} - -#ifdef CONFIG_CHARGER_OTG -int charger_enable_otg_power(int enabled) -{ - int val, rv; - - rv = bq2589x_read(BQ2589X_REG_CFG2, &val); - if (rv) - return rv; - val = (val & ~(BQ2589X_CFG2_CHG_CONFIG | BQ2589X_CFG2_OTG_CONFIG)) - | (enabled ? BQ2589X_CFG2_OTG_CONFIG : BQ2589X_CFG2_CHG_CONFIG); - return bq2589x_write(BQ2589X_REG_CFG2, val); -} -#endif - -int charger_set_input_current(int input_current) -{ - int value, rv; - const struct charger_info * const info = charger_get_info(); - - input_current -= info->input_current_min; - if (input_current < 0) - input_current = 0; - - rv = bq2589x_read(BQ2589X_REG_INPUT_CURR, &value); - if (rv) - return rv; - value = value & ~(0x3f); - value |= (input_current / info->input_current_step) & 0x3f; - return bq2589x_write(BQ2589X_REG_INPUT_CURR, value); -} - -int charger_get_input_current(int *input_current) -{ - int rv, value; - const struct charger_info * const info = charger_get_info(); - - rv = bq2589x_read(BQ2589X_REG_INPUT_CURR, &value); - if (rv) - return rv; - - *input_current = (value & 0x3f) * info->input_current_step - + info->input_current_min; - - return EC_SUCCESS; -} - -int charger_manufacturer_id(int *id) -{ - return EC_ERROR_UNIMPLEMENTED; -} - -int charger_device_id(int *id) -{ - int res = bq2589x_read(BQ2589X_REG_ID, id); - - if (res == EC_SUCCESS) - *id &= BQ2589X_DEVICE_ID_MASK; - - return res; -} - -int charger_get_option(int *option) -{ - /* Ignored: does not exist */ - *option = 0; - return EC_SUCCESS; -} - -int charger_set_option(int option) -{ - /* Ignored: does not exist */ - return EC_SUCCESS; -} - -const struct charger_info *charger_get_info(void) -{ - return &bq2589x_charger_info; -} - -int charger_get_status(int *status) -{ - /* TODO(crosbug.com/p/38603) implement using REG0C value */ - *status = 0; - return EC_SUCCESS; -} - -int charger_set_mode(int mode) -{ - return EC_SUCCESS; -} - -int charger_get_current(int *current) -{ - int rv, val; - const struct charger_info * const info = charger_get_info(); - - rv = bq2589x_read(BQ2589X_REG_CHG_CURR, &val); - if (rv) - return rv; - *current = val * info->current_step + info->current_min; - return EC_SUCCESS; -} - -int charger_set_current(int current) -{ - const struct charger_info * const info = charger_get_info(); - - current = charger_closest_current(current); - - return bq2589x_write(BQ2589X_REG_CHG_CURR, - current / info->current_step); -} - -int charger_get_voltage(int *voltage) -{ - int rv, val; - const struct charger_info * const info = charger_get_info(); - - rv = bq2589x_read(BQ2589X_REG_CHG_VOLT, &val); - if (rv) - return rv; - val = (val >> 2) & 0x3f; - *voltage = val * info->voltage_step + info->voltage_min; - return EC_SUCCESS; -} - -int charger_set_voltage(int voltage) -{ - int rv, val; - const struct charger_info * const info = charger_get_info(); - - voltage = charger_closest_voltage(voltage); - - rv = bq2589x_read(BQ2589X_REG_CHG_VOLT, &val); - if (rv) - return rv; - val = val & 0x3; - val |= ((voltage - info->voltage_min) / info->voltage_step) << 2; - return bq2589x_write(BQ2589X_REG_CHG_VOLT, val); -} - -int charger_discharge_on_ac(int enable) -{ - int rv, val; - - rv = bq2589x_read(BQ2589X_REG_INPUT_CURR, &val); - if (rv) - return rv; - - if (enable) - val |= BQ2589X_INPUT_CURR_EN_HIZ; - else - val &= ~BQ2589X_INPUT_CURR_EN_HIZ; - - return bq2589x_write(BQ2589X_REG_INPUT_CURR, val); -} - -/* Charging power state initialization */ -int charger_post_init(void) -{ -#ifdef CONFIG_CHARGER_ILIM_PIN_DISABLED - int val, rv; - /* Ignore ILIM pin value */ - rv = bq2589x_read(BQ2589X_REG_INPUT_CURR, &val); - if (rv) - return rv; - val &= ~BQ2589X_INPUT_CURR_EN_ILIM; - rv = bq2589x_write(BQ2589X_REG_INPUT_CURR, val); - if (rv) - return rv; -#endif /* CONFIG_CHARGER_ILIM_PIN_DISABLED */ - - /* Input current controlled by extpower module. Do nothing here. */ - return EC_SUCCESS; -} - -/*****************************************************************************/ -/* Hardware current ramping (aka ICO: Input Current Optimizer) */ - -#ifdef CONFIG_CHARGE_RAMP_HW -int charger_set_hw_ramp(int enable) -{ - int val, rv; - - rv = i2c_read8(I2C_PORT_CHARGER, BQ2589X_ADDR, BQ2589X_REG_CFG1, &val); - if (rv) - return rv; - - if (enable) - val |= BQ2589X_CFG1_ICO_EN; - else - val &= ~BQ2589X_CFG1_ICO_EN; - - return i2c_write8(I2C_PORT_CHARGER, BQ2589X_ADDR, BQ2589X_REG_CFG1, - val); -} - -int chg_ramp_is_stable(void) -{ - int val, rv; - - rv = bq2589x_read(BQ2589X_REG_ID, &val); - if (!rv && (val & BQ2589X_ID_ICO_OPTIMIZED)) - return 1; - else - return 0; -} - -int chg_ramp_is_detected(void) -{ - return 1; -} - -int chg_ramp_get_current_limit(void) -{ - int input_ma, rv; - - rv = bq2589x_read(BQ2589X_REG_ADC_INPUT_CURR, &input_ma); - - return rv ? -1 : 100 + (input_ma & 0x3f) * 50; -} -#endif /* CONFIG_CHARGE_RAMP_HW */ - -/*****************************************************************************/ -/* Hooks */ - -static void bq2589x_init(void) -{ - int val; - - if (charger_device_id(&val) || val != BQ2589X_DEVICE_ID) { - CPRINTF("BQ2589X incorrent ID: 0x%02x\n", val); - return; - } - - /* - * Disable I2C watchdog timer. - * - * TODO(crosbug.com/p/38603): Re-enable watchdog timer and kick it - * periodically in charger task. - */ - if (bq2589x_read(BQ2589X_REG_TIMER, &val)) - return; - val &= ~0x30; - if (bq2589x_write(BQ2589X_REG_TIMER, val)) - return; - - if (bq2589x_set_terminate_current(CONFIG_CHARGER_TERM_CURRENT_LIMIT)) - return; - - if (bq2589x_watchdog_reset()) - return; - - if (bq2589x_write(BQ2589X_REG_IR_COMP, CONFIG_CHARGER_BQ2589X_IR_COMP)) - return; - - if (bq2589x_write(BQ2589X_REG_BOOST_MODE, CONFIG_CHARGER_BQ2589X_BOOST)) - return; - - CPRINTF("BQ2589%c initialized\n", - BQ2589X_DEVICE_ID == BQ25890_DEVICE_ID ? '0' : - (BQ2589X_DEVICE_ID == BQ25895_DEVICE_ID ? '5' : '2')); -} -DECLARE_HOOK(HOOK_INIT, bq2589x_init, HOOK_PRIO_LAST); - -/*****************************************************************************/ -/* Console commands */ -#ifdef CONFIG_CMD_CHARGER -static int command_bq2589x(int argc, char **argv) -{ - int i; - int value; - int rv; - int batt_mv, sys_mv, vbus_mv, chg_ma, input_ma; - - /* Trigger one ADC conversion */ - bq2589x_read(BQ2589X_REG_CFG1, &value); - bq2589x_write(BQ2589X_REG_CFG1, value | BQ2589X_CFG1_CONV_START); - do { - bq2589x_read(BQ2589X_REG_CFG1, &value); - } while (value & BQ2589X_CFG1_CONV_START); /* Wait for End of Conv. */ - - bq2589x_read(BQ2589X_REG_ADC_BATT_VOLT, &batt_mv); - bq2589x_read(BQ2589X_REG_ADC_SYS_VOLT, &sys_mv); - bq2589x_read(BQ2589X_REG_ADC_VBUS_VOLT, &vbus_mv); - bq2589x_read(BQ2589X_REG_ADC_CHG_CURR, &chg_ma); - bq2589x_read(BQ2589X_REG_ADC_INPUT_CURR, &input_ma); - ccprintf("ADC Batt %dmV Sys %dmV VBUS %dmV Chg %dmA Input %dmA\n", - 2304 + (batt_mv & 0x7f) * 20, 2304 + sys_mv * 20, - 2600 + (vbus_mv & 0x7f) * 100, - chg_ma * 50, 100 + (input_ma & 0x3f) * 50); - - ccprintf("REG:"); - for (i = 0; i <= 0x14; ++i) - ccprintf(" %02x", i); - ccprintf("\n"); - - ccprintf("VAL:"); - for (i = 0; i <= 0x14; ++i) { - rv = bq2589x_read(i, &value); - if (rv) - return rv; - ccprintf(" %02x", value); - } - ccprintf("\n"); - - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(bq2589x, command_bq2589x, - NULL, NULL); -#endif diff --git a/driver/charger/bq2589x.h b/driver/charger/bq2589x.h deleted file mode 100644 index 95bbf4c226..0000000000 --- a/driver/charger/bq2589x.h +++ /dev/null @@ -1,113 +0,0 @@ -/* 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. - * - * TI bq25890/bq25892/bq25895 battery charger driver. - */ - -#ifndef __CROS_EC_BQ2589X_H -#define __CROS_EC_BQ2589X_H - -/* Registers */ -#define BQ2589X_REG_INPUT_CURR 0x00 -#define BQ2589X_REG_VINDPM 0x01 -#define BQ2589X_REG_CFG1 0x02 -#define BQ2589X_REG_CFG2 0x03 -#define BQ2589X_REG_CHG_CURR 0x04 -#define BQ2589X_REG_PRE_CHG_CURR 0x05 -#define BQ2589X_REG_CHG_VOLT 0x06 -#define BQ2589X_REG_TIMER 0x07 -#define BQ2589X_REG_IR_COMP 0x08 -#define BQ2589X_REG_FORCE 0x09 -#define BQ2589X_REG_BOOST_MODE 0x0A -#define BQ2589X_REG_STATUS 0x0B /* Read-only */ -#define BQ2589X_REG_FAULT 0x0C /* Read-only */ -#define BQ2589X_REG_VINDPM_THRESH 0x0D -#define BQ2589X_REG_ADC_BATT_VOLT 0x0E /* Read-only */ -#define BQ2589X_REG_ADC_SYS_VOLT 0x0F /* Read-only */ -#define BQ2589X_REG_ADC_TS 0x10 /* Read-only */ -#define BQ2589X_REG_ADC_VBUS_VOLT 0x11 /* Read-only */ -#define BQ2589X_REG_ADC_CHG_CURR 0x12 /* Read-only */ -#define BQ2589X_REG_ADC_INPUT_CURR 0x13 /* Read-only */ -#define BQ2589X_REG_ID 0x14 - -/* REG00 : input current register bit definitions */ -#define BQ2589X_INPUT_CURR_EN_HIZ (1<<7) -#define BQ2589X_INPUT_CURR_EN_ILIM (1<<6) - -/* REG02 : first configuration register bit definitions */ -#define BQ2589X_CFG1_CONV_START (1<<7) -#define BQ2589X_CFG1_ICO_EN (1<<4) -#define BQ2589X_CFG1_AUTO_DPDM_EN (1<<0) - -/* REG03 : second configuration register bit definitions */ -#define BQ2589X_CFG2_CHG_CONFIG (1<<4) -#define BQ2589X_CFG2_OTG_CONFIG (1<<5) -#define BQ2589X_CFG2_WD_RST (1<<6) - -/* REG08 : IR compensation definitions */ -#define BQ2589X_IR_BAT_COMP_140MOHM (7 << 5) -#define BQ2589X_IR_BAT_COMP_120MOHM (6 << 5) -#define BQ2589X_IR_BAT_COMP_100MOHM (5 << 5) -#define BQ2589X_IR_BAT_COMP_80MOHM (4 << 5) -#define BQ2589X_IR_BAT_COMP_60MOHM (3 << 5) -#define BQ2589X_IR_BAT_COMP_40MOHM (2 << 5) -#define BQ2589X_IR_BAT_COMP_20MOHM BIT(5) -#define BQ2589X_IR_BAT_COMP_0MOHM (0 << 5) -#define BQ2589X_IR_VCLAMP_224MV (7 << 2) -#define BQ2589X_IR_VCLAMP_192MV (6 << 2) -#define BQ2589X_IR_VCLAMP_160MV (5 << 2) -#define BQ2589X_IR_VCLAMP_128MV (4 << 2) -#define BQ2589X_IR_VCLAMP_96MV (3 << 2) -#define BQ2589X_IR_VCLAMP_64MV (2 << 2) -#define BQ2589X_IR_VCLAMP_32MV BIT(2) -#define BQ2589X_IR_VCLAMP_0MV (0 << 2) -#define BQ2589X_IR_TREG_120C (3 << 0) -#define BQ2589X_IR_TREG_100C (2 << 0) -#define BQ2589X_IR_TREG_80C BIT(0) -#define BQ2589X_IR_TREG_60C (0 << 0) - -#define BQ2589X_IR_COMP_DEFAULT (BQ2589X_IR_TREG_120C | BQ2589X_IR_VCLAMP_0MV |\ - BQ2589X_IR_BAT_COMP_0MOHM) - -#define BQ2589X_TERM_CURRENT_LIMIT_DEFAULT 256 - -/* 5V VBUS Boost settings */ -#define BQ2589X_BOOSTV_MV(mv) (((((mv) - 4550)/64) & 0xF) << 4) -#define BQ2589X_BOOSTV_DEFAULT BQ2589X_BOOSTV_MV(4998) -#define BQ2589X_BOOST_LIM_500MA 0x00 -#define BQ2589X_BOOST_LIM_750MA 0x01 -#define BQ2589X_BOOST_LIM_1200MA 0x02 -#define BQ2589X_BOOST_LIM_1400MA 0x03 -#define BQ2589X_BOOST_LIM_1650MA 0x04 -#define BQ2589X_BOOST_LIM_1875MA 0x05 -#define BQ2589X_BOOST_LIM_2150MA 0x06 -#define BQ2589X_BOOST_LIM_2450MA 0x07 -#define BQ2589X_BOOST_LIM_DEFAULT BQ2589X_BOOST_LIM_1400MA -#define BQ2589X_BOOST_DEFAULT (BQ2589X_BOOST_LIM_DEFAULT |\ - BQ2589X_BOOSTV_DEFAULT) - -/* REG14: Device ID, reset and ICO status */ -#define BQ2589X_DEVICE_ID_MASK 0x38 -#define BQ25890_DEVICE_ID 0x18 -#define BQ25892_DEVICE_ID 0x00 -#define BQ25895_DEVICE_ID 0x38 - -#define BQ2589X_ID_ICO_OPTIMIZED 0x40 - - -/* Variant-specific configuration */ -#if defined(CONFIG_CHARGER_BQ25890) -#define BQ2589X_DEVICE_ID BQ25890_DEVICE_ID -#define BQ2589X_ADDR_FLAGS 0x6A -#elif defined(CONFIG_CHARGER_BQ25895) -#define BQ2589X_DEVICE_ID BQ25895_DEVICE_ID -#define BQ2589X_ADDR_FLAGS 0x6A -#elif defined(CONFIG_CHARGER_BQ25892) -#define BQ2589X_DEVICE_ID BQ25892_DEVICE_ID -#define BQ2589X_ADDR_FLAGS 0x6B -#else -#error BQ2589X unknown variant -#endif - -#endif /* __CROS_EC_BQ2589X_H */ diff --git a/driver/charger/isl923x.c b/driver/charger/isl923x.c deleted file mode 100644 index 7a02f62ca0..0000000000 --- a/driver/charger/isl923x.c +++ /dev/null @@ -1,741 +0,0 @@ -/* 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. - * - * Intersil ISL-9237/8 battery charger driver. - */ - -#include "adc.h" -#include "battery.h" -#include "battery_smart.h" -#include "charger.h" -#include "console.h" -#include "common.h" -#include "hooks.h" -#include "i2c.h" -#include "isl923x.h" -#include "system.h" -#include "task.h" -#include "timer.h" -#include "util.h" - -#ifndef CONFIG_CHARGER_NARROW_VDC -#error "ISL9237/8 is a NVDC charger, please enable CONFIG_CHARGER_NARROW_VDC." -#endif - -#define DEFAULT_R_AC 20 -#define DEFAULT_R_SNS 10 -#define R_AC CONFIG_CHARGER_SENSE_RESISTOR_AC -#define R_SNS CONFIG_CHARGER_SENSE_RESISTOR -#define REG_TO_CURRENT(REG) ((REG) * DEFAULT_R_SNS / R_SNS) -#define CURRENT_TO_REG(CUR) ((CUR) * R_SNS / DEFAULT_R_SNS) -#define AC_REG_TO_CURRENT(REG) ((REG) * DEFAULT_R_AC / R_AC) -#define AC_CURRENT_TO_REG(CUR) ((CUR) * R_AC / DEFAULT_R_AC) - -/* Console output macros */ -#define CPRINTF(format, args...) cprintf(CC_CHARGER, format, ## args) -#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ## args) - -static int learn_mode; - -/* Mutex for CONTROL1 register, that can be updated from multiple tasks. */ -static struct mutex control1_mutex; - -/* Charger parameters */ -static const struct charger_info isl9237_charger_info = { - .name = CHARGER_NAME, - .voltage_max = CHARGE_V_MAX, - .voltage_min = CHARGE_V_MIN, - .voltage_step = CHARGE_V_STEP, - .current_max = REG_TO_CURRENT(CHARGE_I_MAX), - .current_min = REG_TO_CURRENT(CHARGE_I_MIN), - .current_step = REG_TO_CURRENT(CHARGE_I_STEP), - .input_current_max = AC_REG_TO_CURRENT(INPUT_I_MAX), - .input_current_min = AC_REG_TO_CURRENT(INPUT_I_MIN), - .input_current_step = AC_REG_TO_CURRENT(INPUT_I_STEP), -}; - -static inline int raw_read8(int offset, int *value) -{ - return i2c_read8(I2C_PORT_CHARGER, I2C_ADDR_CHARGER_FLAGS, - offset, value); -} - -static inline int raw_read16(int offset, int *value) -{ - return i2c_read16(I2C_PORT_CHARGER, I2C_ADDR_CHARGER_FLAGS, - offset, value); -} - -static inline int raw_write16(int offset, int value) -{ - return i2c_write16(I2C_PORT_CHARGER, I2C_ADDR_CHARGER_FLAGS, - offset, value); -} - -static int isl9237_set_current(uint16_t current) -{ - return raw_write16(ISL923X_REG_CHG_CURRENT, CURRENT_TO_REG(current)); -} - -static int isl9237_set_voltage(uint16_t voltage) -{ - return raw_write16(ISL923X_REG_SYS_VOLTAGE_MAX, voltage); -} - -/* chip specific interfaces */ - -int charger_set_input_current(int input_current) -{ - int rv; - uint16_t reg = AC_CURRENT_TO_REG(input_current); - - rv = raw_write16(ISL923X_REG_ADAPTER_CURRENT1, reg); - if (rv) - return rv; - - return raw_write16(ISL923X_REG_ADAPTER_CURRENT2, reg); -} - -int charger_get_input_current(int *input_current) -{ - int rv; - int reg; - - rv = raw_read16(ISL923X_REG_ADAPTER_CURRENT1, ®); - if (rv) - return rv; - - *input_current = AC_REG_TO_CURRENT(reg); - return EC_SUCCESS; -} - -#if defined(CONFIG_CHARGER_OTG) && defined(CONFIG_CHARGER_ISL9238) -int charger_enable_otg_power(int enabled) -{ - int rv, control1; - - mutex_lock(&control1_mutex); - - rv = raw_read16(ISL923X_REG_CONTROL1, &control1); - if (rv) - goto out; - - if (enabled) - control1 |= ISL923X_C1_OTG; - else - control1 &= ~ISL923X_C1_OTG; - - rv = raw_write16(ISL923X_REG_CONTROL1, control1); - -out: - mutex_unlock(&control1_mutex); - - return rv; -} - -/* - * TODO(b:67920792): OTG is not implemented for ISL9237 that has different - * register scale and range. - */ -int charger_set_otg_current_voltage(int output_current, int output_voltage) -{ - int rv; - uint16_t volt_reg = (output_voltage / ISL9238_OTG_VOLTAGE_STEP) - << ISL9238_OTG_VOLTAGE_SHIFT; - uint16_t current_reg = - DIV_ROUND_UP(output_current, ISL923X_OTG_CURRENT_STEP) - << ISL923X_OTG_CURRENT_SHIFT; - - if (output_current < 0 || output_current > ISL923X_OTG_CURRENT_MAX || - output_voltage > ISL9238_OTG_VOLTAGE_MAX) - return EC_ERROR_INVAL; - - /* Set voltage. */ - rv = raw_write16(ISL923X_REG_OTG_VOLTAGE, volt_reg); - if (rv) - return rv; - - /* Set current. */ - return raw_write16(ISL923X_REG_OTG_CURRENT, current_reg); -} -#endif /* CONFIG_CHARGER_OTG && CONFIG_CHARGER_ISL9238 */ - -int charger_manufacturer_id(int *id) -{ - int rv; - int reg; - - rv = raw_read16(ISL923X_REG_MANUFACTURER_ID, ®); - if (rv) - return rv; - - *id = reg; - return EC_SUCCESS; -} - -int charger_device_id(int *id) -{ - int rv; - int reg; - - rv = raw_read16(ISL923X_REG_DEVICE_ID, ®); - if (rv) - return rv; - - *id = reg; - return EC_SUCCESS; -} - -int charger_get_option(int *option) -{ - int rv; - uint32_t controls; - int reg; - - rv = raw_read16(ISL923X_REG_CONTROL0, ®); - if (rv) - return rv; - - controls = reg; - rv = raw_read16(ISL923X_REG_CONTROL1, ®); - if (rv) - return rv; - - controls |= reg << 16; - *option = controls; - return EC_SUCCESS; -} - -int charger_set_option(int option) -{ - int rv; - uint16_t reg; - - reg = option & 0xffff; - rv = raw_write16(ISL923X_REG_CONTROL0, reg); - - if (rv) - return rv; - - reg = (option >> 16) & 0xffff; - return raw_write16(ISL923X_REG_CONTROL1, reg); -} - -/* Charger interfaces */ - -const struct charger_info *charger_get_info(void) -{ - return &isl9237_charger_info; -} - -int charger_get_status(int *status) -{ - *status = CHARGER_LEVEL_2; - - return EC_SUCCESS; -} - -int charger_set_mode(int mode) -{ - int rv = EC_SUCCESS; - - /* - * See crosbug.com/p/51196. Always disable learn mode unless it was set - * explicitly. - */ - if (!learn_mode) - rv = charger_discharge_on_ac(0); - - /* ISL923X does not support inhibit mode setting. */ - return rv; -} - -int charger_get_current(int *current) -{ - int rv; - int reg; - - rv = raw_read16(ISL923X_REG_CHG_CURRENT, ®); - if (rv) - return rv; - - *current = REG_TO_CURRENT(reg); - return EC_SUCCESS; -} - -int charger_set_current(int current) -{ - return isl9237_set_current(current); -} - -int charger_get_voltage(int *voltage) -{ - return raw_read16(ISL923X_REG_SYS_VOLTAGE_MAX, voltage); -} - -int charger_set_voltage(int voltage) -{ - /* The ISL923X will drop voltage to as low as requested. As the - * charger state machine will pass in 0 voltage, protect the system - * voltage by capping to the minimum. The reason is that the ISL923X - * only can regulate the system voltage which will kill the board's - * power if below 0. */ - if (voltage == 0) { - const struct battery_info *bi = battery_get_info(); - voltage = bi->voltage_min; - } - - return isl9237_set_voltage(voltage); -} - -int charger_post_init(void) -{ - /* - * charger_post_init() is called every time AC becomes present in the - * system. It's called this frequently because there are some charger - * ICs which become unpowered when AC is not present. Therefore, upon - * AC becoming present again, the chargers need to be reinitialized. - * The ISL9237/8 can be powered from VSYS and therefore do not need to - * be reinitialized everytime. This is why isl923x_init() is called - * once at HOOK_INIT time. - */ - return EC_SUCCESS; -} - -int isl923x_set_ac_prochot(uint16_t ma) -{ - int rv; - - if (ma > ISL923X_AC_PROCHOT_CURRENT_MAX) { - CPRINTS("%s: invalid current (%d mA)\n", __func__, ma); - return EC_ERROR_INVAL; - } - - rv = raw_write16(ISL923X_REG_PROCHOT_AC, ma); - if (rv) - CPRINTS("%s failed (%d)", __func__, rv); - return rv; -} - -int isl923x_set_dc_prochot(uint16_t ma) -{ - int rv; - - if (ma > ISL923X_DC_PROCHOT_CURRENT_MAX) { - CPRINTS("%s: invalid current (%d mA)\n", __func__, ma); - return EC_ERROR_INVAL; - } - - rv = raw_write16(ISL923X_REG_PROCHOT_DC, ma); - if (rv) - CPRINTS("%s failed (%d)", __func__, rv); - return rv; -} - -static void isl923x_init(void) -{ - int reg; - -#ifdef CONFIG_TRICKLE_CHARGING - const struct battery_info *bi = battery_get_info(); - int precharge_voltage = bi->precharge_voltage ? - bi->precharge_voltage : bi->voltage_min; - - if (raw_write16(ISL923X_REG_SYS_VOLTAGE_MIN, precharge_voltage)) - goto init_fail; -#endif - - /* - * [10:9]: Prochot# Debounce time - * 11b: 1ms - */ - if (raw_read16(ISL923X_REG_CONTROL2, ®)) - goto init_fail; - - if (raw_write16(ISL923X_REG_CONTROL2, - reg | - ISL923X_C2_OTG_DEBOUNCE_150 | - ISL923X_C2_PROCHOT_DEBOUNCE_1000 | - ISL923X_C2_ADAPTER_DEBOUNCE_150)) - goto init_fail; - -#ifdef CONFIG_CHARGE_RAMP_HW -#ifdef CONFIG_CHARGER_ISL9237 - if (raw_read16(ISL923X_REG_CONTROL0, ®)) - goto init_fail; - - /* Set input voltage regulation reference voltage for charge ramp */ - reg &= ~ISL9237_C0_VREG_REF_MASK; - reg |= ISL9237_C0_VREG_REF_4200; - - if (raw_write16(ISL923X_REG_CONTROL0, reg)) - goto init_fail; -#else /* !defined(CONFIG_CHARGER_ISL9237) */ - /* - * For the ISL9238, set the input voltage regulation to 4.439V. Note, - * the voltage is set in 341.3 mV steps. - */ - reg = (4439 / ISL9238_INPUT_VOLTAGE_REF_STEP) - << ISL9238_INPUT_VOLTAGE_REF_SHIFT; - - if (raw_write16(ISL9238_REG_INPUT_VOLTAGE, reg)) - goto init_fail; -#endif /* defined(CONFIG_CHARGER_ISL9237) */ -#else /* !defined(CONFIG_CHARGE_RAMP_HW) */ - if (raw_read16(ISL923X_REG_CONTROL0, ®)) - goto init_fail; - - /* Disable voltage regulation loop to disable charge ramp */ - reg |= ISL923X_C0_DISABLE_VREG; - - if (raw_write16(ISL923X_REG_CONTROL0, reg)) - goto init_fail; -#endif /* defined(CONFIG_CHARGE_RAMP_HW) */ - -#ifdef CONFIG_CHARGER_ISL9238 - /* - * Don't reread the prog pin and don't reload the ILIM on ACIN. - */ - if (raw_read16(ISL9238_REG_CONTROL3, ®)) - goto init_fail; - reg |= ISL9238_C3_NO_RELOAD_ACLIM_ON_ACIN | - ISL9238_C3_NO_REREAD_PROG_PIN; - /* - * Disable autonomous charging initially since 1) it causes boot loop - * issues with 2S batteries, and 2) it will automatically get disabled - * as soon as we manually set the current limit anyway. - */ - reg |= ISL9238_C3_DISABLE_AUTO_CHARING; - if (raw_write16(ISL9238_REG_CONTROL3, reg)) - goto init_fail; - - /* - * No need to proceed with the rest of init if we sysjump'd to this - * image as the input current limit has already been set. - */ - if (system_jumped_to_this_image()) - return; - - /* - * Initialize the input current limit to the board's default. - */ - if (charger_set_input_current(CONFIG_CHARGER_INPUT_CURRENT)) - goto init_fail; -#endif /* defined(CONFIG_CHARGER_ISL9238) */ - - return; -init_fail: - CPRINTS("%s failed!", __func__); -} -DECLARE_HOOK(HOOK_INIT, isl923x_init, HOOK_PRIO_INIT_I2C + 1); - -int charger_discharge_on_ac(int enable) -{ - int rv; - int control1; - - mutex_lock(&control1_mutex); - - rv = raw_read16(ISL923X_REG_CONTROL1, &control1); - if (rv) - goto out; - - control1 &= ~ISL923X_C1_LEARN_MODE_AUTOEXIT; - if (enable) - control1 |= ISL923X_C1_LEARN_MODE_ENABLE; - else - control1 &= ~ISL923X_C1_LEARN_MODE_ENABLE; - - rv = raw_write16(ISL923X_REG_CONTROL1, control1); - - learn_mode = !rv && enable; - -out: - mutex_unlock(&control1_mutex); - return rv; -} - -/*****************************************************************************/ -/* Hardware current ramping */ - -#ifdef CONFIG_CHARGE_RAMP_HW -int charger_set_hw_ramp(int enable) -{ - int rv, reg; - - rv = raw_read16(ISL923X_REG_CONTROL0, ®); - if (rv) - return rv; - - /* HW ramp is controlled by input voltage regulation reference bits */ - if (enable) - reg &= ~ISL923X_C0_DISABLE_VREG; - else - reg |= ISL923X_C0_DISABLE_VREG; - - return raw_write16(ISL923X_REG_CONTROL0, reg); -} - -int chg_ramp_is_stable(void) -{ - /* - * Since ISL cannot read the current limit that the ramp has settled - * on, then we can never consider the ramp stable, because we never - * know what the stable limit is. - */ - return 0; -} - -int chg_ramp_is_detected(void) -{ - return 1; -} - -int chg_ramp_get_current_limit(void) -{ - /* - * ISL doesn't have a way to get this info, so return the nominal - * current limit as an estimate. - */ - int input_current; - - if (charger_get_input_current(&input_current) != EC_SUCCESS) - return 0; - return input_current; -} -#endif /* CONFIG_CHARGE_RAMP_HW */ - - -#ifdef CONFIG_CHARGER_PSYS -static int psys_enabled; - -static void charger_enable_psys(void) -{ - int val; - - mutex_lock(&control1_mutex); - - /* - * enable system power monitor PSYS function - */ - if (raw_read16(ISL923X_REG_CONTROL1, &val)) - goto out; - - val |= ISL923X_C1_ENABLE_PSYS; - - if (raw_write16(ISL923X_REG_CONTROL1, val)) - goto out; - - psys_enabled = 1; - -out: - mutex_unlock(&control1_mutex); -} -DECLARE_HOOK(HOOK_CHIPSET_STARTUP, charger_enable_psys, HOOK_PRIO_DEFAULT); - -static void charger_disable_psys(void) -{ - int val; - - mutex_lock(&control1_mutex); - - /* - * disable system power monitor PSYS function - */ - if (raw_read16(ISL923X_REG_CONTROL1, &val)) - goto out; - - val &= ~ISL923X_C1_ENABLE_PSYS; - - if (raw_write16(ISL923X_REG_CONTROL1, val)) - goto out; - - psys_enabled = 0; - -out: - mutex_unlock(&control1_mutex); -} -DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, charger_disable_psys, HOOK_PRIO_DEFAULT); - -#ifdef CONFIG_CHARGER_PSYS_READ -int charger_get_system_power(void) -{ - int adc; - - /* - * If PSYS is not enabled, AP is probably off, and the value is usually - * too small to be measured acurately anyway. - */ - if (!psys_enabled) - return -1; - - /* - * We assume that the output gain is always left to the default - * 1.44 uA/W, and that the ADC scaling values are setup accordingly in - * board file, so that the value is indicated in uW. - */ - adc = adc_read_channel(ADC_PSYS); - - return adc; -} - -static int console_command_psys(int argc, char **argv) -{ - ccprintf("PSYS = %d uW\n", charger_get_system_power()); - return 0; -} -DECLARE_CONSOLE_COMMAND(psys, console_command_psys, - NULL, - "Get the system power in mW"); -#endif /* CONFIG_CHARGER_PSYS_READ */ -#endif /* CONFIG_CHARGER_PSYS */ - -#ifdef CONFIG_CMD_CHARGER_ADC_AMON_BMON -enum amon_bmon { AMON, BMON }; - -static int print_amon_bmon(enum amon_bmon amon, int direction, - int resistor) -{ - int adc, curr, reg, ret; - -#ifdef CONFIG_CHARGER_ISL9238 - ret = i2c_read16(I2C_PORT_CHARGER, I2C_ADDR_CHARGER_FLAGS, - ISL9238_REG_CONTROL3, ®); - if (ret) - return ret; - - /* Switch direction */ - if (direction) - reg |= ISL9238_C3_AMON_BMON_DIRECTION; - else - reg &= ~ISL9238_C3_AMON_BMON_DIRECTION; - ret = i2c_write16(I2C_PORT_CHARGER, I2C_ADDR_CHARGER_FLAGS, - ISL9238_REG_CONTROL3, reg); - if (ret) - return ret; -#endif - - mutex_lock(&control1_mutex); - - ret = i2c_read16(I2C_PORT_CHARGER, I2C_ADDR_CHARGER_FLAGS, - ISL923X_REG_CONTROL1, ®); - if (!ret) { - /* Switch between AMON/BMON */ - if (amon == AMON) - reg &= ~ISL923X_C1_SELECT_BMON; - else - reg |= ISL923X_C1_SELECT_BMON; - - /* Enable monitor */ - reg &= ~ISL923X_C1_DISABLE_MON; - ret = i2c_write16(I2C_PORT_CHARGER, I2C_ADDR_CHARGER_FLAGS, - ISL923X_REG_CONTROL1, reg); - } - - mutex_unlock(&control1_mutex); - - if (ret) - return ret; - - adc = adc_read_channel(ADC_AMON_BMON); - curr = adc / resistor; - ccprintf("%cMON(%sharging): %d uV, %d mA\n", amon == AMON ? 'A' : 'B', - direction ? "Disc" : "C", adc, curr); - - return ret; -} - -/** - * Get charger AMON and BMON current. - */ -static int console_command_amon_bmon(int argc, char **argv) -{ - int ret = EC_SUCCESS; - int print_ac = 1; - int print_battery = 1; - int print_charge = 1; - int print_discharge = 1; - - if (argc >= 2) { - print_ac = (argv[1][0] == 'a'); - print_battery = (argv[1][0] == 'b'); -#ifdef CONFIG_CHARGER_ISL9238 - if (argv[1][1] != '\0') { - print_charge = (argv[1][1] == 'c'); - print_discharge = (argv[1][1] == 'd'); - } -#endif - } - - if (print_ac) { - if (print_charge) - ret |= print_amon_bmon(AMON, 0, - CONFIG_CHARGER_SENSE_RESISTOR_AC); -#ifdef CONFIG_CHARGER_ISL9238 - if (print_discharge) - ret |= print_amon_bmon(AMON, 1, - CONFIG_CHARGER_SENSE_RESISTOR_AC); -#endif - } - - if (print_battery) { -#ifdef CONFIG_CHARGER_ISL9238 - if (print_charge) - ret |= print_amon_bmon(BMON, 0, - /* - * charging current monitor has - * 2x amplification factor - */ - 2*CONFIG_CHARGER_SENSE_RESISTOR); -#endif - if (print_discharge) - ret |= print_amon_bmon(BMON, 1, - CONFIG_CHARGER_SENSE_RESISTOR); - } - - return ret; -} -DECLARE_CONSOLE_COMMAND(amonbmon, console_command_amon_bmon, -#ifdef CONFIG_CHARGER_ISL9237 - "amonbmon [a|b]", -#else - "amonbmon [a[c|d]|b[c|d]]", -#endif - "Get charger AMON/BMON voltage diff, current"); -#endif /* CONFIG_CMD_CHARGER_ADC_AMON_BMON */ - -#ifdef CONFIG_CMD_CHARGER_DUMP -static void dump_reg_range(int low, int high) -{ - int reg; - int regval; - int rv; - - for (reg = low; reg <= high; reg++) { - CPRINTF("[%Xh] = ", reg); - rv = i2c_read16(I2C_PORT_CHARGER, I2C_ADDR_CHARGER_FLAGS, - reg, ®val); - if (!rv) - CPRINTF("0x%04x\n", regval); - else - CPRINTF("ERR (%d)\n", rv); - cflush(); - } -} - -static int command_isl923x_dump(int argc, char **argv) -{ - dump_reg_range(0x14, 0x15); - dump_reg_range(0x38, 0x3F); - dump_reg_range(0x47, 0x4A); -#ifdef CONFIG_CHARGER_ISL9238 - dump_reg_range(0x4B, 0x4E); -#endif /* CONFIG_CHARGER_ISL9238 */ - dump_reg_range(0xFE, 0xFF); - - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(charger_dump, command_isl923x_dump, "", - "Dumps ISL923x registers"); -#endif /* CONFIG_CMD_CHARGER_DUMP */ diff --git a/driver/charger/isl923x.h b/driver/charger/isl923x.h deleted file mode 100644 index 8076b72e38..0000000000 --- a/driver/charger/isl923x.h +++ /dev/null @@ -1,316 +0,0 @@ -/* 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. - * - * Intersil ISL-9237/8 battery charger driver. - */ - -#ifndef __CROS_EC_ISL923X_H -#define __CROS_EC_ISL923X_H - -#define ISL923X_ADDR_FLAGS (0x09) - -/* Registers */ -#define ISL923X_REG_CHG_CURRENT 0x14 -#define ISL923X_REG_ADAPTER_CURRENT1 0x3f -#define ISL923X_REG_ADAPTER_CURRENT2 0x3b -#define ISL923X_REG_SYS_VOLTAGE_MAX 0x15 -#define ISL923X_REG_SYS_VOLTAGE_MIN 0x3e -#define ISL923X_REG_PROCHOT_AC 0x47 -#define ISL923X_REG_PROCHOT_DC 0x48 -#define ISL923X_REG_T1_T2 0x38 -#define ISL923X_REG_CONTROL0 0x39 -#define ISL923X_REG_CONTROL1 0x3c -#define ISL923X_REG_CONTROL2 0x3d -#define ISL9238_REG_CONTROL3 0x4c -#define ISL9238_REG_CONTROL4 0x4e -#define ISL923X_REG_INFO 0x3a -#define ISL9238_REG_INFO2 0x4d -#define ISL923X_REG_OTG_VOLTAGE 0x49 -#define ISL923X_REG_OTG_CURRENT 0x4a -#define ISL9238_REG_INPUT_VOLTAGE 0x4b -#define ISL923X_REG_MANUFACTURER_ID 0xfe -#define ISL923X_REG_DEVICE_ID 0xff - -/* Sense resistor default values in mOhm */ -#define ISL923X_DEFAULT_SENSE_RESISTOR_AC 20 -#define ISL923X_DEFAULT_SENSE_RESISTOR 10 - -/* Maximum charging current register value */ -#define ISL923X_CURRENT_REG_MAX 0x17c0 /* bit<12:2> 10111110000 */ - -/* 2-level adpater current limit duration T1 & T2 in micro seconds */ -#define ISL923X_T1_10000 0x00 -#define ISL923X_T1_20000 0x01 -#define ISL923X_T1_15000 0x02 -#define ISL923X_T1_5000 0x03 -#define ISL923X_T1_1000 0x04 -#define ISL923X_T1_500 0x05 -#define ISL923X_T1_100 0x06 -#define ISL923X_T1_0 0x07 -#define ISL923X_T2_10 (0x00 << 8) -#define ISL923X_T2_100 (0x01 << 8) -#define ISL923X_T2_500 (0x02 << 8) -#define ISL923X_T2_1000 (0x03 << 8) -#define ISL923X_T2_300 (0x04 << 8) -#define ISL923X_T2_750 (0x05 << 8) -#define ISL923X_T2_2000 (0x06 << 8) -#define ISL923X_T2_10000 (0x07 << 8) - -#define ISL9237_SYS_VOLTAGE_REG_MAX 13824 -#define ISL9238_SYS_VOLTAGE_REG_MAX 18304 -#define ISL923X_SYS_VOLTAGE_REG_MIN 2048 - -/* PROCHOT# debounce time and duration time in micro seconds */ -#define ISL923X_PROCHOT_DURATION_10000 (0 << 6) -#define ISL923X_PROCHOT_DURATION_20000 BIT(6) -#define ISL923X_PROCHOT_DURATION_15000 (2 << 6) -#define ISL923X_PROCHOT_DURATION_5000 (3 << 6) -#define ISL923X_PROCHOT_DURATION_1000 (4 << 6) -#define ISL923X_PROCHOT_DURATION_500 (5 << 6) -#define ISL923X_PROCHOT_DURATION_100000 (6 << 6) -#define ISL923X_PROCHOT_DURATION_0 (7 << 6) -#define ISL923X_PROCHOT_DURATION_MASK (7 << 6) - -#define ISL923X_PROCHOT_DEBOUNCE_10 (0 << 9) -#define ISL923X_PROCHOT_DEBOUNCE_100 BIT(9) -#define ISL923X_PROCHOT_DEBOUNCE_500 (2 << 9) -#define ISL923X_PROCHOT_DEBOUNCE_1000 (3 << 9) -#define ISL923X_PROCHOT_DEBOUNCE_MASK (3 << 9) - -/* Maximum PROCHOT register value */ -#define ISL923X_PROCHOT_AC_REG_MAX 6400 -#define ISL923X_PROCHOT_DC_REG_MAX 12800 - -/* Control0: adapter voltage regulation reference */ -#define ISL9237_C0_VREG_REF_3900 0 -#define ISL9237_C0_VREG_REF_4200 1 -#define ISL9237_C0_VREG_REF_4500 2 -#define ISL9237_C0_VREG_REF_4800 3 -#define ISL9237_C0_VREG_REF_MASK 0x03 - -/* Control0: disable adapter voltaqe regulation */ -#define ISL923X_C0_DISABLE_VREG BIT(2) - -/* Control0: battery DCHOT reference for RS2 == 20mOhm */ -#define ISL923X_C0_DCHOT_6A (0 << 3) -#define ISL923X_C0_DCHOT_5A BIT(3) -#define ISL923X_C0_DCHOT_4A (2 << 3) -#define ISL923X_C0_DCHOT_3A (3 << 3) -#define ISL923X_C0_DCHOT_MASK (3 << 3) - -/* Control1: general purpose comparator debounce time in micro second */ -#define ISL923X_C1_GP_DEBOUNCE_2 (0 << 14) -#define ISL923X_C1_GP_DEBOUNCE_12 BIT(14) -#define ISL923X_C1_GP_DEBOUNCE_2000 (2 << 14) -#define ISL923X_C1_GP_DEBOUNCE_5000000 (3 << 14) -#define ISL923X_C1_GP_DEBOUNCE_MASK (3 << 14) - -/* Control1: learn mode */ -#define ISL923X_C1_LEARN_MODE_AUTOEXIT BIT(13) -#define ISL923X_C1_LEARN_MODE_ENABLE BIT(12) - -/* Control1: OTG enable */ -#define ISL923X_C1_OTG BIT(11) - -/* Control1: audio filter */ -#define ISL923X_C1_AUDIO_FILTER BIT(10) - -/* Control1: switch frequency, ISL9238 defines bit 7 as unused */ -#define ISL923X_C1_SWITCH_FREQ_PROG (0 << 7) /* 1000kHz or PROG */ -#define ISL9237_C1_SWITCH_FREQ_913K BIT(7) -#define ISL923X_C1_SWITCH_FREQ_839K (2 << 7) -#define ISL9237_C1_SWITCH_FREQ_777K (3 << 7) -#define ISL923X_C1_SWITCH_FREQ_723K (4 << 7) -#define ISL9237_C1_SWITCH_FREQ_676K (5 << 7) -#define ISL923X_C1_SWITCH_FREQ_635K (6 << 7) -#define ISL9237_C1_SWITCH_FREQ_599K (7 << 7) -#define ISL923X_C1_SWITCH_FREQ_MASK (7 << 7) - -/* Control1: turbo mode */ -#define ISL923X_C1_TURBO_MODE BIT(6) - -/* Control1: AMON & BMON */ -#define ISL923X_C1_DISABLE_MON BIT(5) -#define ISL923X_C1_SELECT_BMON BIT(4) - -/* Control1: PSYS, VSYS, VSYSLO */ -#define ISL923X_C1_ENABLE_PSYS BIT(3) -#define ISL923X_C1_ENABLE_VSYS BIT(2) -#define ISL923X_C1_VSYSLO_REF_6000 0 -#define ISL923X_C1_VSYSLO_REF_6300 1 -#define ISL923X_C1_VSYSLO_REF_6600 2 -#define ISL923X_C1_VSYSLO_REF_6900 3 -#define ISL923X_C1_VSYSLO_REF_MASK 3 - -/* Control2: trickle charging current in mA */ -#define ISL923X_C2_TRICKLE_256 (0 << 14) -#define ISL923X_C2_TRICKLE_128 BIT(14) -#define ISL923X_C2_TRICKLE_64 (2 << 14) -#define ISL923X_C2_TRICKLE_512 (3 << 14) -#define ISL923X_C2_TRICKLE_MASK (3 << 14) - -/* Control2: OTGEN debounce time in ms */ -#define ISL923X_C2_OTG_DEBOUNCE_1300 (0 << 13) -#define ISL923X_C2_OTG_DEBOUNCE_150 BIT(13) -#define ISL923X_C2_OTG_DEBOUNCE_MASK BIT(13) - -/* Control2: 2-level adapter over current */ -#define ISL923X_C2_2LVL_OVERCURRENT BIT(12) - -/* Control2: adapter insertion debounce time in ms */ -#define ISL923X_C2_ADAPTER_DEBOUNCE_1300 (0 << 11) -#define ISL923X_C2_ADAPTER_DEBOUNCE_150 BIT(11) -#define ISL923X_C2_ADAPTER_DEBOUNCE_MASK BIT(11) - -/* Control2: PROCHOT debounce time in uS */ -#define ISL9238_C2_PROCHOT_DEBOUNCE_7 (0 << 9) -#define ISL9237_C2_PROCHOT_DEBOUNCE_10 (0 << 9) -#define ISL923X_C2_PROCHOT_DEBOUNCE_100 BIT(9) -#define ISL923X_C2_PROCHOT_DEBOUNCE_500 (2 << 9) -#define ISL923X_C2_PROCHOT_DEBOUNCE_1000 (3 << 9) -#define ISL923X_C2_PROCHOT_DEBOUNCE_MASK (3 << 9) - -/* Control2: min PROCHOT duration in uS */ -#define ISL923X_C2_PROCHOT_DURATION_10000 (0 << 6) -#define ISL923X_C2_PROCHOT_DURATION_20000 BIT(6) -#define ISL923X_C2_PROCHOT_DURATION_15000 (2 << 6) -#define ISL923X_C2_PROCHOT_DURATION_5000 (3 << 6) -#define ISL923X_C2_PROCHOT_DURATION_1000 (4 << 6) -#define ISL923X_C2_PROCHOT_DURATION_500 (5 << 6) -#define ISL923X_C2_PROCHOT_DURATION_100 (6 << 6) -#define ISL923X_C2_PROCHOT_DURATION_0 (7 << 6) -#define ISL923X_C2_PROCHOT_DURATION_MASK (7 << 6) - -/* Control2: turn off ASGATE in OTG mode */ -#define ISL923X_C2_ASGATE_OFF BIT(5) - -/* Control2: CMIN, general purpose comparator reference in mV */ -#define ISL923X_C2_CMIN_2000 (0 << 4) -#define ISL923X_C2_CMIN_1200 BIT(4) - -/* Control2: general purpose comparator enable */ -#define ISL923X_C2_COMPARATOR BIT(3) - -/* Control2: invert CMOUT, general purpose comparator output, polarity */ -#define ISL923X_C2_INVERT_CMOUT BIT(2) - -/* Control2: disable WOC, way over current */ -#define ISL923X_C2_WOC_OFF BIT(1) - -/* Control2: PSYS gain in uA/W (ISL9237 only) */ -#define ISL9237_C2_PSYS_GAIN BIT(0) - -/* - * Control3: Buck-Boost switching period - * 0: x1 frequency, 1: half frequency. - */ -#define ISL9238_C3_BB_SWITCHING_PERIOD BIT(1) - -/* - * Control3: AMON/BMON direction. - * 0: adapter/charging, 1:OTG/discharging (ISL9238 only) - */ -#define ISL9238_C3_AMON_BMON_DIRECTION BIT(3) - -/* - * Control3: Disables Autonomous Charing - * - * Note: This is disabled automatically when ever we set the current limit - * manually (which we always do). - */ -#define ISL9238_C3_DISABLE_AUTO_CHARING BIT(7) - -/* Control3: PSYS gain in uA/W (ISL9238 only) */ -#define ISL9238_C3_PSYS_GAIN BIT(9) - -/* Control3: Don't reload ACLIM on ACIN. */ -#define ISL9238_C3_NO_RELOAD_ACLIM_ON_ACIN BIT(14) - -/* Control3: Don't reread PROG pin. */ -#define ISL9238_C3_NO_REREAD_PROG_PIN BIT(15) - -/* OTG voltage limit in mV, current limit in mA */ -#define ISL9237_OTG_VOLTAGE_MIN 4864 -#define ISL9237_OTG_VOLTAGE_MAX 5376 -#define ISL9238_OTG_VOLTAGE_MAX 27456 -#define ISL923X_OTG_CURRENT_MAX 4096 - -#define ISL9238_OTG_VOLTAGE_STEP 12 -#define ISL9238_OTG_VOLTAGE_SHIFT 3 -#define ISL923X_OTG_CURRENT_STEP 128 -#define ISL923X_OTG_CURRENT_SHIFT 7 - -/* Input voltage regulation voltage reference */ -#define ISL9238_INPUT_VOLTAGE_REF_STEP 341 -#define ISL9238_INPUT_VOLTAGE_REF_SHIFT 8 - -/* Info register fields */ -#define ISL9237_INFO_PROG_RESISTOR_MASK 0xf -#define ISL923X_INFO_TRICKLE_ACTIVE_MASK BIT(4) -#define ISL9237_INFO_PSTATE_SHIFT 5 -#define ISL9237_INFO_PSTATE_MASK 3 - -enum isl9237_power_stage { - BUCK_MODE, - BOOST_MODE, - BUCK_BOOST_MODE, - REVERSE_BUCK_MODE -}; - -#define ISL9237_INFO_FSM_STATE_SHIFT 7 -#define ISL9237_INFO_FSM_STATE_MASK 7 - -enum isl9237_fsm_state { - FSM_OFF, - FSM_BAT, - FSM_ADPT, - FSM_ACOK, - FSM_VSYS, - FSM_CHRG, - FSM_ENTOG, - FSM_OTG -}; - -#define ISL923X_INFO_VSYSLO BIT(10) -#define ISL923X_INFO_DCHOT BIT(11) -#define ISL9237_INFO_ACHOT BIT(12) - -#if defined(CONFIG_CHARGER_ISL9237) -#define CHARGER_NAME "isl9237" -#define CHARGE_V_MAX ISL9237_SYS_VOLTAGE_REG_MAX -#define CHARGE_V_MIN ISL923X_SYS_VOLTAGE_REG_MIN -#define CHARGE_V_STEP 8 -#elif defined(CONFIG_CHARGER_ISL9238) -#define CHARGER_NAME "isl9238" -#define CHARGE_V_MAX ISL9238_SYS_VOLTAGE_REG_MAX -#define CHARGE_V_MIN ISL923X_SYS_VOLTAGE_REG_MIN -#define CHARGE_V_STEP 8 -#endif - -#define CHARGE_I_MAX ISL923X_CURRENT_REG_MAX -#define CHARGE_I_MIN 4 -#define CHARGE_I_OFF 0 -#define CHARGE_I_STEP 4 -#define INPUT_I_MAX ISL923X_CURRENT_REG_MAX -#define INPUT_I_MIN 4 -#define INPUT_I_STEP 4 - -#define I2C_ADDR_CHARGER_FLAGS ISL923X_ADDR_FLAGS -#endif /* __CROS_EC_ISL923X_H */ - -/** - * Initialize AC & DC prochot threshold - * - * @param AC Porchot threshold current in mA: - * multiple of 128 up to 6400 mA - * DC Porchot threshold current in mA: - * multiple of 128 up to 12800 mA - * Bits below 128mA are truncated (ignored). - * @return enum ec_error_list - */ -int isl923x_set_ac_prochot(uint16_t ma); -int isl923x_set_dc_prochot(uint16_t ma); - -#define ISL923X_AC_PROCHOT_CURRENT_MAX 6400 /* mA */ -#define ISL923X_DC_PROCHOT_CURRENT_MAX 12800 /* mA */ diff --git a/driver/charger/isl9241.c b/driver/charger/isl9241.c deleted file mode 100644 index 436b1bc981..0000000000 --- a/driver/charger/isl9241.c +++ /dev/null @@ -1,466 +0,0 @@ -/* Copyright 2019 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. - * - * Renesas (Intersil) ISL-9241 battery charger driver. - */ - -#include "adc.h" -#include "battery.h" -#include "battery_smart.h" -#include "charger.h" -#include "console.h" -#include "common.h" -#include "hooks.h" -#include "i2c.h" -#include "isl9241.h" -#include "system.h" -#include "task.h" -#include "timer.h" -#include "util.h" - -#ifndef CONFIG_CHARGER_NARROW_VDC -#error "ISL9241 is a NVDC charger, please enable CONFIG_CHARGER_NARROW_VDC." -#endif - -/* Sense resistor default values in milli Ohm */ -#define ISL9241_DEFAULT_RS1 20 /* Input current sense resistor */ -#define ISL9241_DEFAULT_RS2 10 /* Battery charge current sense resistor */ - -#define BOARD_RS1 CONFIG_CHARGER_SENSE_RESISTOR_AC -#define BOARD_RS2 CONFIG_CHARGER_SENSE_RESISTOR - -#define BC_REG_TO_CURRENT(REG) (((REG) * ISL9241_DEFAULT_RS2) / BOARD_RS2) -#define BC_CURRENT_TO_REG(CUR) (((CUR) * BOARD_RS2) / ISL9241_DEFAULT_RS2) - -#define AC_REG_TO_CURRENT(REG) (((REG) * ISL9241_DEFAULT_RS1) / BOARD_RS1) -#define AC_CURRENT_TO_REG(CUR) (((CUR) * BOARD_RS1) / ISL9241_DEFAULT_RS1) - -/* Console output macros */ -#define CPRINTF(format, args...) cprintf(CC_CHARGER, format, ## args) - -static int learn_mode; - -/* Mutex for CONTROL1 register, that can be updated from multiple tasks. */ -static struct mutex control1_mutex; - -/* Charger parameters */ -static const struct charger_info isl9241_charger_info = { - .name = CHARGER_NAME, - .voltage_max = CHARGE_V_MAX, - .voltage_min = CHARGE_V_MIN, - .voltage_step = CHARGE_V_STEP, - .current_max = CHARGE_I_MAX, - .current_min = CHARGE_I_MIN, - .current_step = CHARGE_I_STEP, - .input_current_max = INPUT_I_MAX, - .input_current_min = INPUT_I_MIN, - .input_current_step = INPUT_I_STEP, -}; - -static inline int isl9241_read(int offset, int *value) -{ - return i2c_read16(I2C_PORT_CHARGER, I2C_ADDR_CHARGER_FLAGS, - offset, value); -} - -static inline int isl9241_write(int offset, int value) -{ - return i2c_write16(I2C_PORT_CHARGER, I2C_ADDR_CHARGER_FLAGS, - offset, value); -} - -/* chip specific interfaces */ - -/*****************************************************************************/ -/* Charger interfaces */ -int charger_set_input_current(int input_current) -{ - int rv; - uint16_t reg = AC_CURRENT_TO_REG(input_current); - - rv = isl9241_write(ISL9241_REG_ADAPTER_CUR_LIMIT1, reg); - if (rv) - return rv; - - return isl9241_write(ISL9241_REG_ADAPTER_CUR_LIMIT2, reg); -} - -int charger_get_input_current(int *input_current) -{ - int rv; - - rv = isl9241_read(ISL9241_REG_ADAPTER_CUR_LIMIT1, input_current); - if (rv) - return rv; - - *input_current = AC_REG_TO_CURRENT(*input_current); - return EC_SUCCESS; -} - -int charger_manufacturer_id(int *id) -{ - return isl9241_read(ISL9241_REG_MANUFACTURER_ID, id); -} - -int charger_device_id(int *id) -{ - return isl9241_read(ISL9241_REG_DEVICE_ID, id); -} - -int charger_get_option(int *option) -{ - int rv; - uint32_t controls; - int reg; - - rv = isl9241_read(ISL9241_REG_CONTROL0, ®); - if (rv) - return rv; - - controls = reg; - rv = isl9241_read(ISL9241_REG_CONTROL1, ®); - if (rv) - return rv; - - controls |= reg << 16; - *option = controls; - return EC_SUCCESS; -} - -int charger_set_option(int option) -{ - int rv; - - rv = isl9241_write(ISL9241_REG_CONTROL0, option & 0xFFFF); - if (rv) - return rv; - - return isl9241_write(ISL9241_REG_CONTROL1, (option >> 16) & 0xFFFF); -} - -const struct charger_info *charger_get_info(void) -{ - return &isl9241_charger_info; -} - -int charger_get_status(int *status) -{ - int rv; - int reg; - - /* Level 2 charger */ - *status = CHARGER_LEVEL_2; - - /* Charge inhibit status */ - rv = isl9241_read(ISL9241_REG_MIN_SYSTEM_VOLTAGE, ®); - if (rv) - return rv; - if (!reg) - *status |= CHARGER_CHARGE_INHIBITED; - - /* Battery present & AC present status */ - rv = isl9241_read(ISL9241_REG_INFORMATION2, ®); - if (rv) - return rv; - if (!(reg & ISL9241_INFORMATION2_BATGONE_PIN)) - *status |= CHARGER_BATTERY_PRESENT; - if (reg & ISL9241_INFORMATION2_ACOK_PIN) - *status |= CHARGER_AC_PRESENT; - - return EC_SUCCESS; -} - -int charger_set_mode(int mode) -{ - int rv; - - /* - * See crosbug.com/p/51196. Always disable learn mode unless it was set - * explicitly. - */ - if (!learn_mode) { - rv = charger_discharge_on_ac(0); - if (rv) - return rv; - } - - /* - * Charger inhibit - * MinSystemVoltage 0x00h = disables all battery charging - */ - rv = isl9241_write(ISL9241_REG_MIN_SYSTEM_VOLTAGE, - mode & CHARGE_FLAG_INHIBIT_CHARGE ? - 0 : battery_get_info()->voltage_min); - if (rv) - return rv; - - /* POR reset */ - if (mode & CHARGE_FLAG_POR_RESET) { - rv = isl9241_write(ISL9241_REG_CONTROL3, - ISL9241_CONTROL3_DIGITAL_RESET); - } - - return rv; -} - -int charger_get_current(int *current) -{ - int rv; - - rv = isl9241_read(ISL9241_REG_CHG_CURRENT_LIMIT, current); - if (rv) - return rv; - - *current = BC_REG_TO_CURRENT(*current); - return EC_SUCCESS; -} - -int charger_set_current(int current) -{ - return isl9241_write(ISL9241_REG_CHG_CURRENT_LIMIT, - BC_CURRENT_TO_REG(current)); -} - -int charger_get_voltage(int *voltage) -{ - return isl9241_read(ISL9241_REG_MAX_SYSTEM_VOLTAGE, voltage); -} - -int charger_set_voltage(int voltage) -{ - return isl9241_write(ISL9241_REG_MAX_SYSTEM_VOLTAGE, voltage); -} - -int charger_get_vbus_voltage(int port) -{ - int adc_val = 0; - int ctl3_val; - int rv; - - /* Get current Control3 value */ - rv = isl9241_read(ISL9241_REG_CONTROL3, &ctl3_val); - if (rv) - goto error; - - /* Enable ADC */ - if (!(ctl3_val & ISL9241_CONTROL3_ENABLE_ADC)) { - rv = isl9241_write(ISL9241_REG_CONTROL3, - ctl3_val | ISL9241_CONTROL3_ENABLE_ADC); - if (rv) - goto error; - } - - /* Read voltage ADC value */ - rv = isl9241_read(ISL9241_REG_VIN_ADC_RESULTS, &adc_val); - if (rv) - goto error_restore_ctl3; - - /* - * Adjust adc_val - * - * raw adc_val has VIN_ADC in bits [13:6], so shift this down - * this puts adc_val in the range of 0..255, which maps to 0..24.48V - * each step in adc_val is 96mv - */ - adc_val >>= ISL9241_VIN_ADC_BIT_OFFSET; - adc_val *= ISL9241_VIN_ADC_STEP_MV; - -error_restore_ctl3: - /* Restore Control3 value */ - if (!(ctl3_val & ISL9241_CONTROL3_ENABLE_ADC)) - (void)isl9241_write(ISL9241_REG_CONTROL3, ctl3_val); - -error: - if (rv) - CPRINTF("Could not read VBUS ADC! Error: %d\n", rv); - - return adc_val; -} - -int charger_post_init(void) -{ - return EC_SUCCESS; -} - -int charger_discharge_on_ac(int enable) -{ - int rv; - int control1; - - mutex_lock(&control1_mutex); - - rv = isl9241_read(ISL9241_REG_CONTROL1, &control1); - if (rv) - goto out; - - if (enable) - control1 |= ISL9241_CONTROL1_LEARN_MODE; - else - control1 &= ~ISL9241_CONTROL1_LEARN_MODE; - - rv = isl9241_write(ISL9241_REG_CONTROL1, control1); - if (!rv) - learn_mode = enable; - -out: - mutex_unlock(&control1_mutex); - return rv; -} - -/*****************************************************************************/ -/* ISL-9241 initialization */ -static void isl9241_init(void) -{ - int reg; - - const struct battery_info *bi = battery_get_info(); - - /* - * Set the MaxSystemVoltage to battery maximum, - * 0x00=disables switching charger states - */ - if (isl9241_write(ISL9241_REG_MAX_SYSTEM_VOLTAGE, bi->voltage_max)) - goto init_fail; - - /* - * Set the MinSystemVoltage to battery minimum, - * 0x00=disables all battery charging - */ - if (isl9241_write(ISL9241_REG_MIN_SYSTEM_VOLTAGE, bi->voltage_min)) - goto init_fail; - - /* - * Set control2 register to - * [15:13]: Trickle Charging Current (battery pre-charge current) - * [12] : Two-Level Adapter Current Limit (enable) - * [10:9] : Prochot# Debounce time (1000us) - */ - if (isl9241_read(ISL9241_REG_CONTROL2, ®)) - goto init_fail; - - if (isl9241_write(ISL9241_REG_CONTROL2, - reg | ISL9241_CONTROL2_TRICKLE_CHG_CURR(bi->precharge_current) | - ISL9241_CONTROL2_TWO_LEVEL_ADP_CURR | - ISL9241_CONTROL2_PROCHOT_DEBOUNCE_1000)) - goto init_fail; - - /* - * Set control3 register to - * [14]: ACLIM Reload (Do not reload) - */ - if (isl9241_read(ISL9241_REG_CONTROL3, ®)) - goto init_fail; - - if (isl9241_write(ISL9241_REG_CONTROL3, - reg | ISL9241_CONTROL3_ACLIM_RELOAD)) - goto init_fail; - -#ifndef CONFIG_CHARGE_RAMP_HW - if (isl9241_read(ISL9241_REG_CONTROL0, ®)) - goto init_fail; - if (isl9241_write(ISL9241_REG_CONTROL0, - reg | ISL9241_CONTROL0_INPUT_VTG_REGULATION)) - goto init_fail; -#endif - - /* - * No need to proceed with the rest of init if we sysjump'd to this - * image as the input current limit has already been set. - */ - if (system_jumped_to_this_image()) - return; - - /* Initialize the input current limit to the board's default. */ - if (charger_set_input_current(CONFIG_CHARGER_INPUT_CURRENT)) - goto init_fail; - - return; - -init_fail: - CPRINTF("ISL9241_init failed!"); -} -DECLARE_HOOK(HOOK_INIT, isl9241_init, HOOK_PRIO_INIT_I2C + 1); - -/*****************************************************************************/ -/* Hardware current ramping */ - -#ifdef CONFIG_CHARGE_RAMP_HW -int charger_set_hw_ramp(int enable) -{ - int rv, reg; - - rv = isl9241_read(ISL9241_REG_CONTROL0, ®); - if (rv) - return rv; - - /* HW ramp is controlled by input voltage regulation reference bits */ - if (enable) - reg &= ~ISL9241_CONTROL0_INPUT_VTG_REGULATION; - else - reg |= ISL9241_CONTROL0_INPUT_VTG_REGULATION; - - return isl9241_write(ISL9241_REG_CONTROL0, reg); -} - -int chg_ramp_is_stable(void) -{ - /* - * Since ISL cannot read the current limit that the ramp has settled - * on, then we can never consider the ramp stable, because we never - * know what the stable limit is. - */ - return 0; -} - -int chg_ramp_is_detected(void) -{ - return 1; -} - -int chg_ramp_get_current_limit(void) -{ - int reg; - - if (isl9241_read(ISL9241_REG_IADP_ADC_RESULTS, ®)) - return 0; - - /* LSB value of register = 22.2mA */ - return (reg * 222) / 10; -} -#endif /* CONFIG_CHARGE_RAMP_HW */ - -/*****************************************************************************/ -#ifdef CONFIG_CMD_CHARGER_DUMP -static void dump_reg_range(int low, int high) -{ - int reg; - int regval; - int rv; - - for (reg = low; reg <= high; reg++) { - CPRINTF("[%Xh] = ", reg); - rv = isl9241_read(reg, ®val); - if (!rv) - CPRINTF("0x%04x\n", regval); - else - CPRINTF("ERR (%d)\n", rv); - cflush(); - } -} - -static int command_isl9241_dump(int argc, char **argv) -{ - dump_reg_range(0x14, 0x15); - dump_reg_range(0x38, 0x40); - dump_reg_range(0x43, 0x43); - dump_reg_range(0x47, 0x4F); - dump_reg_range(0x80, 0x87); - dump_reg_range(0x90, 0x91); - dump_reg_range(0xFE, 0xFF); - - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(charger_dump, command_isl9241_dump, "", - "Dumps ISL9241 registers"); -#endif /* CONFIG_CMD_CHARGER_DUMP */ diff --git a/driver/charger/isl9241.h b/driver/charger/isl9241.h deleted file mode 100644 index b14c15f780..0000000000 --- a/driver/charger/isl9241.h +++ /dev/null @@ -1,120 +0,0 @@ -/* Copyright 2019 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. - * - * Renesas (Intersil) ISL-9241 battery charger driver header. - */ - -#ifndef __CROS_EC_ISL9241_H -#define __CROS_EC_ISL9241_H - -#define ISL9241_ADDR_FLAGS 0x09 -#define I2C_ADDR_CHARGER_FLAGS ISL9241_ADDR_FLAGS - -#define CHARGER_NAME "ISL9241" -#define CHARGE_V_MAX 18304 -#define CHARGE_V_MIN 64 -#define CHARGE_V_STEP 8 -#define CHARGE_I_MAX 6140 -#define CHARGE_I_MIN 4 -#define CHARGE_I_STEP 4 -#define INPUT_I_MAX 6140 -#define INPUT_I_MIN 4 -#define INPUT_I_STEP 4 - -/* Registers */ - -/* - * ChargeCurrentLimit [12:2] 11-bit (0x0000h = disables fast charging, - * trickle charging is allowed) - */ -#define ISL9241_REG_CHG_CURRENT_LIMIT 0x14 - -/* MaxSystemVoltage [14:3] 12-bit, (0x0000h = disables switching) */ -#define ISL9241_REG_MAX_SYSTEM_VOLTAGE 0x15 - -#define ISL9241_REG_CONTROL7 0x38 - -/* Configures various charger options */ -#define ISL9241_REG_CONTROL0 0x39 -/* 2: Input Voltage Regulation (0 = Enable (default), 1 = Disable) */ -#define ISL9241_CONTROL0_INPUT_VTG_REGULATION BIT(2) - -#define ISL9241_REG_INFORMATION1 0x3A -#define ISL9241_REG_ADAPTER_CUR_LIMIT2 0x3B - -/* Configures various charger options */ -#define ISL9241_REG_CONTROL1 0x3C -#define ISL9241_CONTROL1_LEARN_MODE BIT(12) - -/* Configures various charger options */ -#define ISL9241_REG_CONTROL2 0x3D -/* - * 15:13 - Trickle Charging Current - * <000> 32mA (do not use) - * <001> 64mA - * <010> 96mA - * <011> 128mA (default) - * <100> 160mA - * <101> 192mA - * <110> 224mA - * <111> 256mA - */ -#define ISL9241_CONTROL2_TRICKLE_CHG_CURR(curr) ((((curr) >> 5) - 1) << 13) -/* 12 - Two-Level Adapter Current Limit */ -#define ISL9241_CONTROL2_TWO_LEVEL_ADP_CURR BIT(12) -/* 10:9 PROCHOT# debounce time in uS */ -#define ISL9241_CONTROL2_PROCHOT_DEBOUNCE_1000 (3 << 9) - -/* MinSystemVoltage [13:6] 8-bit (0x0000h = disables all battery charging) */ -#define ISL9241_REG_MIN_SYSTEM_VOLTAGE 0x3E - -#define ISL9241_REG_ADAPTER_CUR_LIMIT1 0x3F -#define ISL9241_REG_ACOK_REFERENCE 0x40 -#define ISL9241_REG_CONTROL6 0x43 -#define ISL9241_REG_AC_PROCHOT 0x47 -#define ISL9241_REG_DC_PROCHOT 0x48 -#define ISL9241_REG_OTG_VOLTAGE 0x49 -#define ISL9241_REG_OTG_CURRENT 0x4A - -/* VIN Voltage (ADP Min Voltage) (default 4.096V) */ -#define ISL9241_REG_VIN_VOLTAGE 0x4B - -/* Configures various charger options */ -#define ISL9241_REG_CONTROL3 0x4C -/* 14: ACLIM Reload (0 - reload, 1 - Do not reload */ -#define ISL9241_CONTROL3_ACLIM_RELOAD BIT(14) -/* 2: Digital Reset (0 - Idle, 1 - Reset */ -#define ISL9241_CONTROL3_DIGITAL_RESET BIT(2) -/* 0: Enable ADC (0 - Active when charging, 1 - Active always) */ -#define ISL9241_CONTROL3_ENABLE_ADC BIT(0) - -/* Indicates various charger status */ -#define ISL9241_REG_INFORMATION2 0x4D -/* 12: BATGONE pin status (0 = Battery is present, 1 = No battery) */ -#define ISL9241_INFORMATION2_BATGONE_PIN BIT(12) -/* 14: ACOK pin status (0 = No adapter, 1 = Adapter is present) */ -#define ISL9241_INFORMATION2_ACOK_PIN BIT(14) - -#define ISL9241_REG_CONTROL4 0x4E -#define ISL9241_REG_CONTROL5 0x4F -#define ISL9241_REG_NTC_ADC_RESULTS 0x80 -#define ISL9241_REG_VBAT_ADC_RESULTS 0x81 -#define ISL9241_REG_TJ_ADC_RESULTS 0x82 - -/* ADC result for adapter current measurements, LSB = 22.2mA */ -#define ISL9241_REG_IADP_ADC_RESULTS 0x83 - -#define ISL9241_REG_DC_ADC_RESULTS 0x84 -#define ISL9241_REG_CC_ADC_RESULTS 0x85 -#define ISL9241_REG_VSYS_ADC_RESULTS 0x86 -#define ISL9241_REG_VIN_ADC_RESULTS 0x87 -#define ISL9241_REG_INFORMATION3 0x90 -#define ISL9241_REG_INFORMATION4 0x91 -#define ISL9241_REG_MANUFACTURER_ID 0xFE -#define ISL9241_REG_DEVICE_ID 0xFF - -#define ISL9241_VIN_ADC_BIT_OFFSET 6 -#define ISL9241_VIN_ADC_STEP_MV 96 - -#endif /* __CROS_EC_ISL9241_H */ diff --git a/driver/charger/rt946x.c b/driver/charger/rt946x.c deleted file mode 100644 index 342aa704f7..0000000000 --- a/driver/charger/rt946x.c +++ /dev/null @@ -1,1682 +0,0 @@ -/* Copyright 2017 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. - * - * Richtek rt946x, Mediatek mt6370 battery charger driver. - */ - -#include "battery.h" -#include "battery_smart.h" -#include "charger.h" -#include "charge_manager.h" -#include "common.h" -#include "compile_time_macros.h" -#include "config.h" -#include "console.h" -#include "hooks.h" -#include "i2c.h" -#include "printf.h" -#include "driver/wpc/p9221.h" -#include "rt946x.h" -#include "task.h" -#include "timer.h" -#include "usb_charge.h" -#include "util.h" - -/* Console output macros */ -#define CPRINTF(format, args...) cprintf(CC_CHARGER, format, ## args) -#define CPRINTS(format, args...) cprints(CC_CHARGER, "CHG " format, ## args) - -/* Charger parameters */ -static const struct charger_info rt946x_charger_info = { - .name = CHARGER_NAME, - .voltage_max = CHARGE_V_MAX, - .voltage_min = CHARGE_V_MIN, - .voltage_step = CHARGE_V_STEP, - .current_max = CHARGE_I_MAX, - .current_min = CHARGE_I_MIN, - .current_step = CHARGE_I_STEP, - .input_current_max = INPUT_I_MAX, - .input_current_min = INPUT_I_MIN, - .input_current_step = INPUT_I_STEP, -}; - -static const struct rt946x_init_setting default_init_setting = { - .eoc_current = 400, - .mivr = 4000, - .ircmp_vclamp = 32, - .ircmp_res = 25, - .boost_voltage = 5050, - .boost_current = 1500, -}; - -__attribute__((weak)) -const struct rt946x_init_setting *board_rt946x_init_setting(void) -{ - return &default_init_setting; -} - -enum rt946x_ilmtsel { - RT946X_ILMTSEL_PSEL_OTG, - RT946X_ILMTSEL_AICR = 2, - RT946X_ILMTSEL_LOWER_LEVEL, /* lower of above two */ -}; - -enum rt946x_chg_stat { - RT946X_CHGSTAT_READY = 0, - RT946X_CHGSTAT_IN_PROGRESS, - RT946X_CHGSTAT_DONE, - RT946X_CHGSTAT_FAULT, -}; - -enum rt946x_adc_in_sel { - RT946X_ADC_VBUS_DIV5 = 1, - RT946X_ADC_VBUS_DIV2, - MT6370_ADC_TS_BAT = 6, - MT6370_ADC_IBUS = 8, - MT6370_ADC_TEMP_JC = 12, - MT6370_ADC_MAX, -}; - -static struct mutex adc_access_lock; - -#ifdef CONFIG_CHARGER_MT6370 -/* - * Unit for each ADC parameter - * 0 stands for reserved - */ -static const int mt6370_adc_unit[MT6370_ADC_MAX] = { - 0, - MT6370_ADC_UNIT_VBUS_DIV5, - MT6370_ADC_UNIT_VBUS_DIV2, - MT6370_ADC_UNIT_VSYS, - MT6370_ADC_UNIT_VBAT, - 0, - MT6370_ADC_UNIT_TS_BAT, - 0, - MT6370_ADC_UNIT_IBUS, - MT6370_ADC_UNIT_IBAT, - 0, - MT6370_ADC_UNIT_CHG_VDDP, - MT6370_ADC_UNIT_TEMP_JC, -}; - -static const int mt6370_adc_offset[MT6370_ADC_MAX] = { - 0, - MT6370_ADC_OFFSET_VBUS_DIV5, - MT6370_ADC_OFFSET_VBUS_DIV2, - MT6370_ADC_OFFSET_VSYS, - MT6370_ADC_OFFSET_VBAT, - 0, - MT6370_ADC_OFFSET_TS_BAT, - 0, - MT6370_ADC_OFFSET_IBUS, - MT6370_ADC_OFFSET_IBAT, - 0, - MT6370_ADC_OFFSET_CHG_VDDP, - MT6370_ADC_OFFSET_TEMP_JC, -}; - -static int hidden_mode_cnt = 0; -static struct mutex hidden_mode_lock; -static const unsigned char mt6370_reg_en_hidden_mode[] = { - MT6370_REG_HIDDENPASCODE1, - MT6370_REG_HIDDENPASCODE2, - MT6370_REG_HIDDENPASCODE3, - MT6370_REG_HIDDENPASCODE4, -}; - -static const unsigned char mt6370_val_en_hidden_mode[] = { - 0x96, 0x69, 0xC3, 0x3C, -}; -#endif /* CONFIG_CHARGER_MT6370 */ - -#if defined(CONFIG_CHARGER_RT9466) || defined(CONFIG_CHARGER_RT9467) -enum rt946x_irq { - RT946X_IRQ_CHGSTATC = 0, - RT946X_IRQ_CHGFAULT, - RT946X_IRQ_TSSTATC, - RT946X_IRQ_CHGIRQ1, - RT946X_IRQ_CHGIRQ2, - RT946X_IRQ_CHGIRQ3, -#ifdef CONFIG_CHARGER_RT9467 - RT946X_IRQ_DPDMIRQ, -#endif - RT946X_IRQ_COUNT, -}; - -static uint8_t rt946x_irqmask[RT946X_IRQ_COUNT] = { - 0xF0, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, -#ifdef CONFIG_CHARGER_RT9467 - 0xFC, -#endif -}; - -static const uint8_t rt946x_irq_maskall[RT946X_IRQ_COUNT] = { - 0xF0, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, -#ifdef CONFIG_CHARGER_RT9467 - 0xFF, -#endif -}; -#elif defined(CONFIG_CHARGER_MT6370) -enum rt946x_irq { - MT6370_IRQ_CHGSTAT1 = 0, - MT6370_IRQ_CHGSTAT2, - MT6370_IRQ_CHGSTAT3, - MT6370_IRQ_CHGSTAT4, - MT6370_IRQ_CHGSTAT5, - MT6370_IRQ_CHGSTAT6, - MT6370_IRQ_DPDMSTAT, - MT6370_IRQ_DICHGSTAT, - MT6370_IRQ_OVPCTRLSTAT, - MT6370_IRQ_FLEDSTAT1, - MT6370_IRQ_FLEDSTAT2, - MT6370_IRQ_BASESTAT, - MT6370_IRQ_LDOSTAT, - MT6370_IRQ_RGBSTAT, - MT6370_IRQ_BLSTAT, - MT6370_IRQ_DBSTAT, - RT946X_IRQ_COUNT, -}; - -static uint8_t rt946x_irqmask[RT946X_IRQ_COUNT] = { - 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, -}; - -static const uint8_t rt946x_irq_maskall[RT946X_IRQ_COUNT] = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, -}; -#endif - -/* Must be in ascending order */ -static const uint16_t rt946x_boost_current[] = { - 500, 700, 1100, 1300, 1800, 2100, 2400, -}; - -static int rt946x_read8(int reg, int *val) -{ - return i2c_read8(I2C_PORT_CHARGER, RT946X_ADDR_FLAGS, reg, val); -} - -static int rt946x_write8(int reg, int val) -{ - return i2c_write8(I2C_PORT_CHARGER, RT946X_ADDR_FLAGS, reg, val); -} - -static int rt946x_block_write(int reg, const uint8_t *val, int len) -{ - return i2c_write_block(I2C_PORT_CHARGER, RT946X_ADDR_FLAGS, - reg, val, len); -} - -static int rt946x_update_bits(int reg, int mask, int val) -{ - int rv; - int reg_val = 0; - - rv = rt946x_read8(reg, ®_val); - if (rv) - return rv; - reg_val &= ~mask; - reg_val |= (mask & val); - rv = rt946x_write8(reg, reg_val); - return rv; -} - -static inline int rt946x_set_bit(int reg, int mask) -{ - return rt946x_update_bits(reg, mask, mask); -} - -static inline int rt946x_clr_bit(int reg, int mask) -{ - return rt946x_update_bits(reg, mask, 0x00); -} - -static inline int mt6370_pmu_reg_test_bit(int cmd, int shift, int *is_one) -{ - int rv, data; - - rv = rt946x_read8(cmd, &data); - if (rv) { - *is_one = 0; - return rv; - } - - *is_one = !!(data & BIT(shift)); - return rv; -} - -static inline uint8_t rt946x_closest_reg(uint16_t min, uint16_t max, - uint16_t step, uint16_t target) -{ - if (target < min) - return 0; - if (target >= max) - return ((max - min) / step); - return (target - min) / step; -} - -static int rt946x_get_ieoc(uint32_t *ieoc) -{ - int ret, reg_ieoc; - - ret = rt946x_read8(RT946X_REG_CHGCTRL9, ®_ieoc); - if (ret) - return ret; - - *ieoc = RT946X_IEOC_MIN + - RT946X_IEOC_STEP * - ((reg_ieoc & RT946X_MASK_IEOC) >> RT946X_SHIFT_IEOC); - - return EC_SUCCESS; -} - -#ifdef CONFIG_CHARGER_MT6370 -static int mt6370_enable_hidden_mode(int en) -{ - int rv = 0; - - if (in_interrupt_context()) { - CPRINTS("Shouldn't use %s in IRQ", __func__); - return EC_ERROR_INVAL; - } - - mutex_lock(&hidden_mode_lock); - if (en) { - if (hidden_mode_cnt == 0) { - rv = rt946x_block_write(mt6370_reg_en_hidden_mode[0], - mt6370_val_en_hidden_mode, - ARRAY_SIZE(mt6370_val_en_hidden_mode)); - if (rv) - goto out; - } - hidden_mode_cnt++; - } else { - if (hidden_mode_cnt == 1) /* last one */ - rv = rt946x_write8(mt6370_reg_en_hidden_mode[0], 0x00); - hidden_mode_cnt--; - if (rv) - goto out; - } - -out: - mutex_unlock(&hidden_mode_lock); - return rv; -} -#endif /* CONFIG_CHARGER_MT6370 */ - -static int rt946x_chip_rev(int *chip_rev) -{ - int rv; - - rv = rt946x_read8(RT946X_REG_DEVICEID, chip_rev); - if (rv == EC_SUCCESS) - *chip_rev &= RT946X_MASK_CHIP_REV; - return rv; -} - -static inline int rt946x_enable_wdt(int en) -{ - return (en ? rt946x_set_bit : rt946x_clr_bit) - (RT946X_REG_CHGCTRL13, RT946X_MASK_WDT_EN); -} - -/* Enable high-impedance mode */ -static inline int rt946x_enable_hz(int en) -{ - return (en ? rt946x_set_bit : rt946x_clr_bit) - (RT946X_REG_CHGCTRL1, RT946X_MASK_HZ_EN); -} - -int rt946x_por_reset(void) -{ - int rv, val; - -#ifdef CONFIG_CHARGER_MT6370 - /* Soft reset. It takes only 1ns for resetting. b/116682788 */ - val = RT946X_MASK_SOFT_RST; - /* - * MT6370 has to set passcodes before resetting all the registers and - * logics. - */ - rv = rt946x_write8(MT6370_REG_RSTPASCODE1, MT6370_MASK_RSTPASCODE1); - rv |= rt946x_write8(MT6370_REG_RSTPASCODE2, MT6370_MASK_RSTPASCODE2); -#else - /* Hard reset, may take several milliseconds. */ - val = RT946X_MASK_RST; - rv = rt946x_enable_hz(0); -#endif - if (rv) - return rv; - - return rt946x_set_bit(RT946X_REG_CORECTRL_RST, val); -} - -static int rt946x_reset_to_zero(void) -{ - int rv; - - rv = charger_set_current(0); - if (rv) - return rv; - - rv = charger_set_voltage(0); - if (rv) - return rv; - - return rt946x_enable_hz(1); -} - -static int rt946x_enable_bc12_detection(int en) -{ -#if defined(CONFIG_CHARGER_RT9467) || defined(CONFIG_CHARGER_MT6370) - int rv; - - if (en) { -#ifdef CONFIG_CHARGER_MT6370_BC12_GPIO - gpio_set_level(GPIO_BC12_DET_EN, 1); -#endif /* CONFIG_CHARGER_MT6370_BC12_GPIO */ - return rt946x_set_bit(RT946X_REG_DPDM1, RT946X_MASK_USBCHGEN); - } - - rv = rt946x_clr_bit(RT946X_REG_DPDM1, RT946X_MASK_USBCHGEN); -#ifdef CONFIG_CHARGER_MT6370_BC12_GPIO - gpio_set_level(GPIO_BC12_DET_EN, 0); -#endif /* CONFIG_CHARGER_MT6370_BC12_GPIO */ - return rv; -#endif - return 0; -} - -static int rt946x_set_ieoc(unsigned int ieoc) -{ - uint8_t reg_ieoc; - - reg_ieoc = rt946x_closest_reg(RT946X_IEOC_MIN, RT946X_IEOC_MAX, - RT946X_IEOC_STEP, ieoc); - - CPRINTF("%s ieoc = %d(0x%02X)\n", __func__, ieoc, reg_ieoc); - - return rt946x_update_bits(RT946X_REG_CHGCTRL9, RT946X_MASK_IEOC, - reg_ieoc << RT946X_SHIFT_IEOC); -} - -static int rt946x_set_mivr(unsigned int mivr) -{ - uint8_t reg_mivr = 0; - - reg_mivr = rt946x_closest_reg(RT946X_MIVR_MIN, RT946X_MIVR_MAX, - RT946X_MIVR_STEP, mivr); - - CPRINTF("%s: mivr = %d(0x%02X)\n", __func__, mivr, reg_mivr); - - return rt946x_update_bits(RT946X_REG_CHGCTRL6, RT946X_MASK_MIVR, - reg_mivr << RT946X_SHIFT_MIVR); -} - -static int rt946x_set_boost_voltage(unsigned int voltage) -{ - uint8_t reg_voltage = 0; - - reg_voltage = rt946x_closest_reg(RT946X_BOOST_VOLTAGE_MIN, - RT946X_BOOST_VOLTAGE_MAX, RT946X_BOOST_VOLTAGE_STEP, voltage); - - CPRINTF("%s voltage = %d(0x%02X)\n", __func__, voltage, reg_voltage); - - return rt946x_update_bits(RT946X_REG_CHGCTRL5, - RT946X_MASK_BOOST_VOLTAGE, - reg_voltage << RT946X_SHIFT_BOOST_VOLTAGE); -} - -static int rt946x_set_boost_current(unsigned int current) -{ - int i; - - /* - * Find the smallest output current threshold which can support - * our requested output current. Use the greatest achievable - * boost current (2.4A) if requested current is too large. - */ - for (i = 0; i < ARRAY_SIZE(rt946x_boost_current) - 1; i++) { - if (current < rt946x_boost_current[i]) - break; - } - - CPRINTF("%s current = %d(0x%02X)\n", __func__, current, i); - - return rt946x_update_bits(RT946X_REG_CHGCTRL10, - RT946X_MASK_BOOST_CURRENT, - i << RT946X_SHIFT_BOOST_CURRENT); -} - -static int rt946x_set_ircmp_vclamp(unsigned int vclamp) -{ - uint8_t reg_vclamp = 0; - - reg_vclamp = rt946x_closest_reg(RT946X_IRCMP_VCLAMP_MIN, - RT946X_IRCMP_VCLAMP_MAX, RT946X_IRCMP_VCLAMP_STEP, vclamp); - - CPRINTF("%s: vclamp = %d(0x%02X)\n", __func__, vclamp, reg_vclamp); - - return rt946x_update_bits(RT946X_REG_CHGCTRL18, - RT946X_MASK_IRCMP_VCLAMP, - reg_vclamp << RT946X_SHIFT_IRCMP_VCLAMP); -} - -static int rt946x_set_ircmp_res(unsigned int res) -{ - uint8_t reg_res = 0; - - reg_res = rt946x_closest_reg(RT946X_IRCMP_RES_MIN, RT946X_IRCMP_RES_MAX, - RT946X_IRCMP_RES_STEP, res); - - CPRINTF("%s: res = %d(0x%02X)\n", __func__, res, reg_res); - - return rt946x_update_bits(RT946X_REG_CHGCTRL18, RT946X_MASK_IRCMP_RES, - reg_res << RT946X_SHIFT_IRCMP_RES); -} - -static int rt946x_set_vprec(unsigned int vprec) -{ - uint8_t reg_vprec = 0; - - reg_vprec = rt946x_closest_reg(RT946X_VPREC_MIN, RT946X_VPREC_MAX, - RT946X_VPREC_STEP, vprec); - - CPRINTF("%s: vprec = %d(0x%02X)\n", __func__, vprec, reg_vprec); - - return rt946x_update_bits(RT946X_REG_CHGCTRL8, RT946X_MASK_VPREC, - reg_vprec << RT946X_SHIFT_VPREC); -} - -static int rt946x_set_iprec(unsigned int iprec) -{ - uint8_t reg_iprec = 0; - - reg_iprec = rt946x_closest_reg(RT946X_IPREC_MIN, RT946X_IPREC_MAX, - RT946X_IPREC_STEP, iprec); - - CPRINTF("%s: iprec = %d(0x%02X)\n", __func__, iprec, reg_iprec); - - return rt946x_update_bits(RT946X_REG_CHGCTRL8, RT946X_MASK_IPREC, - reg_iprec << RT946X_SHIFT_IPREC); -} - -static int rt946x_init_irq(void) -{ - int rv = 0; - int dummy; - int i; - - /* Mask all interrupts */ - rv = rt946x_block_write(RT946X_REG_CHGSTATCCTRL, rt946x_irq_maskall, - RT946X_IRQ_COUNT); - if (rv) - return rv; - - /* Clear all interrupt flags */ - for (i = 0; i < RT946X_IRQ_COUNT; i++) { - rv = rt946x_read8(RT946X_REG_CHGSTATC + i, &dummy); - if (rv) - return rv; - } - - /* Init interrupt */ - return rt946x_block_write(RT946X_REG_CHGSTATCCTRL, rt946x_irqmask, - ARRAY_SIZE(rt946x_irqmask)); -} - -static int rt946x_init_setting(void) -{ - int rv = 0; - const struct battery_info *batt_info = battery_get_info(); - const struct rt946x_init_setting *setting = board_rt946x_init_setting(); - -#ifdef CONFIG_CHARGER_OTG - /* Disable boost-mode output voltage */ - rv = charger_enable_otg_power(0); - if (rv) - return rv; -#endif - /* Enable/Disable BC 1.2 detection */ -#ifdef HAS_TASK_USB_CHG - rv = rt946x_enable_bc12_detection(1); -#else - rv = rt946x_enable_bc12_detection(0); -#endif - if (rv) - return rv; - /* Disable WDT */ - rv = rt946x_enable_wdt(0); - if (rv) - return rv; - /* Disable battery thermal protection */ - rv = rt946x_clr_bit(RT946X_REG_CHGCTRL16, RT946X_MASK_JEITA_EN); - if (rv) - return rv; - /* Disable charge timer */ - rv = rt946x_clr_bit(RT946X_REG_CHGCTRL12, RT946X_MASK_TMR_EN); - if (rv) - return rv; - rv = rt946x_set_mivr(setting->mivr); - if (rv) - return rv; - rv = rt946x_set_ieoc(setting->eoc_current); - if (rv) - return rv; - rv = rt946x_set_boost_voltage( - setting->boost_voltage); - if (rv) - return rv; - rv = rt946x_set_boost_current( - setting->boost_current); - if (rv) - return rv; - rv = rt946x_set_ircmp_vclamp(setting->ircmp_vclamp); - if (rv) - return rv; - rv = rt946x_set_ircmp_res(setting->ircmp_res); - if (rv) - return rv; - rv = rt946x_set_vprec(batt_info->precharge_voltage ? - batt_info->precharge_voltage : batt_info->voltage_min); - if (rv) - return rv; - rv = rt946x_set_iprec(batt_info->precharge_current); - if (rv) - return rv; - -#ifdef CONFIG_CHARGER_MT6370_BACKLIGHT - rt946x_write8(MT6370_BACKLIGHT_BLEN, - MT6370_MASK_BLED_EXT_EN | MT6370_MASK_BLED_EN | - MT6370_MASK_BLED_1CH_EN | MT6370_MASK_BLED_2CH_EN | - MT6370_MASK_BLED_3CH_EN | MT6370_MASK_BLED_4CH_EN | - MT6370_BLED_CODE_LINEAR); - rt946x_update_bits(MT6370_BACKLIGHT_BLPWM, MT6370_MASK_BLPWM_BLED_PWM, - BIT(MT6370_SHIFT_BLPWM_BLED_PWM)); -#endif - - return rt946x_init_irq(); -} - -#ifdef CONFIG_CHARGER_OTG -int charger_enable_otg_power(int enabled) -{ - return (enabled ? rt946x_set_bit : rt946x_clr_bit) - (RT946X_REG_CHGCTRL1, RT946X_MASK_OPA_MODE); -} - -int charger_is_sourcing_otg_power(int port) -{ - int val; - - if (rt946x_read8(RT946X_REG_CHGCTRL1, &val)) - return 0; - - return !!(val & RT946X_MASK_OPA_MODE); -} -#endif - -int charger_set_input_current(int input_current) -{ - uint8_t reg_iin = 0; - const struct charger_info * const info = charger_get_info(); - - reg_iin = rt946x_closest_reg(info->input_current_min, - info->input_current_max, info->input_current_step, - input_current); - - CPRINTF("%s iin = %d(0x%02X)\n", __func__, input_current, reg_iin); - - return rt946x_update_bits(RT946X_REG_CHGCTRL3, RT946X_MASK_AICR, - reg_iin << RT946X_SHIFT_AICR); -} - -int charger_get_input_current(int *input_current) -{ - int rv; - int val = 0; - const struct charger_info * const info = charger_get_info(); - - rv = rt946x_read8(RT946X_REG_CHGCTRL3, &val); - if (rv) - return rv; - - val = (val & RT946X_MASK_AICR) >> RT946X_SHIFT_AICR; - *input_current = val * info->input_current_step - + info->input_current_min; - - return EC_SUCCESS; -} - -int charger_manufacturer_id(int *id) -{ - return EC_ERROR_UNIMPLEMENTED; -} - -int charger_device_id(int *id) -{ - int rv; - - rv = rt946x_read8(RT946X_REG_DEVICEID, id); - if (rv == EC_SUCCESS) - *id &= RT946X_MASK_VENDOR_ID; - return rv; -} - -int charger_get_option(int *option) -{ - /* Ignored: does not exist */ - *option = 0; - return EC_SUCCESS; -} - -int charger_set_option(int option) -{ - /* Ignored: does not exist */ - return EC_SUCCESS; -} - -const struct charger_info *charger_get_info(void) -{ - return &rt946x_charger_info; -} - -int charger_get_status(int *status) -{ - int rv; - int val = 0; - - rv = rt946x_read8(RT946X_REG_CHGCTRL2, &val); - if (rv) - return rv; - val = (val & RT946X_MASK_CHG_EN) >> RT946X_SHIFT_CHG_EN; - if (!val) - *status |= CHARGER_CHARGE_INHIBITED; - - rv = rt946x_read8(RT946X_REG_CHGFAULT, &val); - if (rv) - return rv; - if (val & RT946X_MASK_CHG_VBATOV) - *status |= CHARGER_VOLTAGE_OR; - - - rv = rt946x_read8(RT946X_REG_CHGNTC, &val); - if (rv) - return rv; - val = (val & RT946X_MASK_BATNTC_FAULT) >> RT946X_SHIFT_BATNTC_FAULT; - - switch (val) { - case RT946X_BATTEMP_WARM: - *status |= CHARGER_RES_HOT; - break; - case RT946X_BATTEMP_COOL: - *status |= CHARGER_RES_COLD; - break; - case RT946X_BATTEMP_COLD: - *status |= CHARGER_RES_COLD; - *status |= CHARGER_RES_UR; - break; - case RT946X_BATTEMP_HOT: - *status |= CHARGER_RES_HOT; - *status |= CHARGER_RES_OR; - break; - default: - break; - } - - return EC_SUCCESS; -} - -int charger_set_mode(int mode) -{ - int rv; - - if (mode & CHARGE_FLAG_POR_RESET) { - rv = rt946x_por_reset(); - if (rv) - return rv; - } - - if (mode & CHARGE_FLAG_RESET_TO_ZERO) { - rv = rt946x_reset_to_zero(); - if (rv) - return rv; - } - - return EC_SUCCESS; -} - -int charger_get_current(int *current) -{ - int rv; - int val = 0; - const struct charger_info * const info = charger_get_info(); - - rv = rt946x_read8(RT946X_REG_CHGCTRL7, &val); - if (rv) - return rv; - - val = (val & RT946X_MASK_ICHG) >> RT946X_SHIFT_ICHG; - *current = val * info->current_step + info->current_min; - - return EC_SUCCESS; -} - -int charger_set_current(int current) -{ - int rv; - uint8_t reg_icc; - static int workaround; - const struct charger_info *const info = charger_get_info(); - - /* - * mt6370's minimun regulated current is 500mA REG17[7:2] 0b100, - * values below 0b100 are preserved. - */ - if (IS_ENABLED(CONFIG_CHARGER_MT6370)) - current = MAX(500, current); - - - reg_icc = rt946x_closest_reg(info->current_min, info->current_max, - info->current_step, current); - - rv = rt946x_update_bits(RT946X_REG_CHGCTRL7, RT946X_MASK_ICHG, - reg_icc << RT946X_SHIFT_ICHG); - if (rv) - return rv; - - if (IS_ENABLED(CONFIG_CHARGER_RT9466) || - IS_ENABLED(CONFIG_CHARGER_MT6370)) { - uint32_t curr_ieoc; - - /* - * workaround to make IEOC accurate: - * witht normal charging (ICC >= 900mA), the power path is fully - * turned on. But at low charging current state (ICC < 900mA), - * the power path will only be partially turned on. So under - * such situation, the IEOC is inaccurate. - */ - rv = rt946x_get_ieoc(&curr_ieoc); - if (rv) - return rv; - - if (current < 900 && !workaround) { - /* raise IEOC if charge current is under 900 */ - rv = rt946x_set_ieoc(curr_ieoc + 100); - workaround = 1; - } else if (current >= 900 && workaround) { - /* reset IEOC if charge current is above 900 */ - workaround = 0; - rv = rt946x_set_ieoc(curr_ieoc - 100); - } - } - - return rv; -} - -int charger_get_voltage(int *voltage) -{ - int rv; - int val = 0; - const struct charger_info * const info = charger_get_info(); - - rv = rt946x_read8(RT946X_REG_CHGCTRL4, &val); - if (rv) - return rv; - - val = (val & RT946X_MASK_CV) >> RT946X_SHIFT_CV; - *voltage = val * info->voltage_step + info->voltage_min; - - return EC_SUCCESS; -} - -int charger_set_voltage(int voltage) -{ - uint8_t reg_cv = 0; - const struct charger_info * const info = charger_get_info(); - - reg_cv = rt946x_closest_reg(info->voltage_min, info->voltage_max, - info->voltage_step, voltage); - - return rt946x_update_bits(RT946X_REG_CHGCTRL4, RT946X_MASK_CV, - reg_cv << RT946X_SHIFT_CV); -} - -int charger_discharge_on_ac(int enable) -{ - return rt946x_enable_hz(enable); -} - -/* Setup sourcing current to prevent overload */ -#ifdef CONFIG_CHARGER_ILIM_PIN_DISABLED -static int rt946x_enable_ilim_pin(int en) -{ - int ret; - - ret = (en ? rt946x_set_bit : rt946x_clr_bit) - (RT946X_REG_CHGCTRL3, RT946X_MASK_ILIMEN); - - return ret; -} - -static int rt946x_select_ilmt(enum rt946x_ilmtsel sel) -{ - int ret; - - ret = rt946x_update_bits(RT946X_REG_CHGCTRL2, RT946X_MASK_ILMTSEL, - sel << RT946X_SHIFT_ILMTSEL); - - return ret; -} -#endif /* CONFIG_CHARGER_ILIM_PIN_DISABLED */ - -/* Charging power state initialization */ -int charger_post_init(void) -{ -#ifdef CONFIG_CHARGER_ILIM_PIN_DISABLED - int rv; - - rv = rt946x_select_ilmt(RT946X_ILMTSEL_AICR); - if (rv) - return rv; - /* Disable ILIM pin */ - rv = rt946x_enable_ilim_pin(0); - if (rv) - return rv; -#endif - return EC_SUCCESS; -} - -/* Hardware current ramping (aka AICL: Average Input Current Level) */ -#ifdef CONFIG_CHARGE_RAMP_HW -static int rt946x_get_mivr(int *mivr) -{ - int rv; - int val = 0; - - rv = rt946x_read8(RT946X_REG_CHGCTRL6, &val); - if (rv) - return rv; - - val = (val & RT946X_MASK_MIVR) >> RT946X_SHIFT_MIVR; - *mivr = val * RT946X_MIVR_STEP + RT946X_MIVR_MIN; - - return EC_SUCCESS; -} - -static int rt946x_set_aicl_vth(uint8_t aicl_vth) -{ - uint8_t reg_aicl_vth = 0; - - reg_aicl_vth = rt946x_closest_reg(RT946X_AICLVTH_MIN, - RT946X_AICLVTH_MAX, RT946X_AICLVTH_STEP, aicl_vth); - - return rt946x_update_bits(RT946X_REG_CHGCTRL14, RT946X_MASK_AICLVTH, - reg_aicl_vth << RT946X_SHIFT_AICLVTH); -} - -int charger_set_hw_ramp(int enable) -{ - int rv; - unsigned int mivr = 0; - - if (!enable) { - rv = rt946x_clr_bit(RT946X_REG_CHGCTRL14, RT946X_MASK_AICLMEAS); - return rv; - } - - rv = rt946x_get_mivr(&mivr); - if (rv < 0) - return rv; - - /* - * Check if there's a suitable AICL_VTH. - * The vendor suggests setting AICL_VTH as (MIVR + 200mV). - */ - if ((mivr + 200) > RT946X_AICLVTH_MAX) { - CPRINTF("%s: no suitable vth, mivr = %d\n", __func__, mivr); - return EC_ERROR_INVAL; - } - - rv = rt946x_set_aicl_vth(mivr + 200); - if (rv < 0) - return rv; - - return rt946x_set_bit(RT946X_REG_CHGCTRL14, RT946X_MASK_AICLMEAS); -} - -int chg_ramp_is_stable(void) -{ - int rv; - int val = 0; - - rv = rt946x_read8(RT946X_REG_CHGCTRL14, &val); - val = (val & RT946X_MASK_AICLMEAS) >> RT946X_SHIFT_AICLMEAS; - - return (!rv && !val); -} - -int chg_ramp_is_detected(void) -{ - return 1; -} - -int chg_ramp_get_current_limit(void) -{ - int rv; - int input_current = 0; - - rv = charger_get_input_current(&input_current); - - return rv ? -1 : input_current; -} -#endif /* CONFIG_CHARGE_RAMP_HW */ - -static void rt946x_init(void) -{ - int reg = 0xFFFFFFFF; - - /* Check device id */ - if (charger_device_id(®) || reg != RT946X_VENDOR_ID) { - CPRINTF("RT946X incorrect ID: 0x%02x\n", reg); - return; - } - - /* Check revision id */ - if (rt946x_chip_rev(®)) { - CPRINTF("Failed to read RT946X CHIP REV\n"); - return; - } - CPRINTF("RT946X CHIP REV: 0x%02x\n", reg); - - if (rt946x_init_setting()) { - CPRINTF("RT946X init failed\n"); - return; - } - CPRINTF("RT946X init succeeded\n"); -} -DECLARE_HOOK(HOOK_INIT, rt946x_init, HOOK_PRIO_INIT_I2C + 1); - -#ifdef HAS_TASK_USB_CHG -#ifdef CONFIG_CHARGER_MT6370 -static int mt6370_detect_apple_samsung_ta(int usb_stat) -{ - int ret, reg; - int chg_type = - (usb_stat & MT6370_MASK_USB_STATUS) >> MT6370_SHIFT_USB_STATUS; - int dp_2_3v, dm_2_3v; - - /* Only SDP/CDP/DCP could possibly be Apple/Samsung TA */ - if (chg_type != MT6370_CHG_TYPE_SDPNSTD && - chg_type != MT6370_CHG_TYPE_CDP && - chg_type != MT6370_CHG_TYPE_DCP) - return chg_type; - - if (chg_type == MT6370_CHG_TYPE_SDPNSTD || - chg_type == MT6370_CHG_TYPE_CDP) - if (!(usb_stat & MT6370_MASK_DCD_TIMEOUT)) - return chg_type; - - /* Check D+ > 0.9V */ - ret = rt946x_update_bits(MT6370_REG_QCSTATUS2, MT6360_MASK_CHECK_DPDM, - MT6370_MASK_APP_SS_EN | MT6370_MASK_APP_SS_PL); - ret |= rt946x_read8(MT6370_REG_QCSTATUS2, ®); - - if (ret) - return chg_type; - - /* Normal port (D+ < 0.9V) */ - if (!(reg & MT6370_MASK_SS_OUT)) - return chg_type; - - /* Samsung charger (D+ < 1.5V) */ - if (!(reg & MT6370_MASK_APP_OUT)) - return MT6370_CHG_TYPE_SAMSUNG_CHARGER; - - /* Check D+ > 2.3 V */ - ret = rt946x_update_bits(MT6370_REG_QCSTATUS2, MT6360_MASK_CHECK_DPDM, - MT6370_MASK_APP_REF | MT6370_MASK_APP_SS_PL | - MT6370_MASK_APP_SS_EN); - ret |= rt946x_read8(MT6370_REG_QCSTATUS2, ®); - dp_2_3v = reg & MT6370_MASK_APP_OUT; - - /* Check D- > 2.3 V */ - ret |= rt946x_update_bits( - MT6370_REG_QCSTATUS2, MT6360_MASK_CHECK_DPDM, - MT6370_MASK_APP_REF | MT6370_MASK_APP_DPDM_IN | - MT6370_MASK_APP_SS_PL | MT6370_MASK_APP_SS_EN); - ret |= rt946x_read8(MT6370_REG_QCSTATUS2, ®); - dm_2_3v = reg & MT6370_MASK_APP_OUT; - - if (ret) - return chg_type; - - /* Apple charger */ - if (!dp_2_3v && !dm_2_3v) - /* Apple 2.5W charger */ - return MT6370_CHG_TYPE_APPLE_0_5A_CHARGER; - else if (!dp_2_3v && dm_2_3v) - /* Apple 5W charger */ - return MT6370_CHG_TYPE_APPLE_1_0A_CHARGER; - else if (dp_2_3v && !dm_2_3v) - /* Apple 10W charger */ - return MT6370_CHG_TYPE_APPLE_2_1A_CHARGER; - else - /* Apple 12W charger */ - return MT6370_CHG_TYPE_APPLE_2_4A_CHARGER; -} -#endif - -static int mt6370_get_bc12_device_type(int charger_type) -{ - switch (charger_type) { - case MT6370_CHG_TYPE_SDP: - case MT6370_CHG_TYPE_SDPNSTD: - return CHARGE_SUPPLIER_BC12_SDP; - case MT6370_CHG_TYPE_CDP: - return CHARGE_SUPPLIER_BC12_CDP; - case MT6370_CHG_TYPE_DCP: - case MT6370_CHG_TYPE_SAMSUNG_CHARGER: - case MT6370_CHG_TYPE_APPLE_0_5A_CHARGER: - case MT6370_CHG_TYPE_APPLE_1_0A_CHARGER: - case MT6370_CHG_TYPE_APPLE_2_1A_CHARGER: - case MT6370_CHG_TYPE_APPLE_2_4A_CHARGER: - return CHARGE_SUPPLIER_BC12_DCP; - default: - return CHARGE_SUPPLIER_NONE; - } -} - -/* Returns a mt6370 charger_type. */ -static int mt6370_get_charger_type(void) -{ -#ifdef CONFIG_CHARGER_MT6370 - int reg; - - if (rt946x_read8(MT6370_REG_USBSTATUS1, ®)) - return CHARGE_SUPPLIER_NONE; - return mt6370_detect_apple_samsung_ta(reg); -#else - return CHARGE_SUPPLIER_NONE; -#endif -} - -static int mt6370_get_bc12_ilim(int charge_supplier) -{ - switch (charge_supplier) { - case MT6370_CHG_TYPE_APPLE_0_5A_CHARGER: - return 500; - case MT6370_CHG_TYPE_APPLE_1_0A_CHARGER: - return 1000; - case MT6370_CHG_TYPE_APPLE_2_1A_CHARGER: - if (IS_ENABLED(CONFIG_CHARGE_RAMP_SW) || - IS_ENABLED(CONFIG_CHARGE_RAMP_HW)) - return 2100; - case MT6370_CHG_TYPE_APPLE_2_4A_CHARGER: - if (IS_ENABLED(CONFIG_CHARGE_RAMP_SW) || - IS_ENABLED(CONFIG_CHARGE_RAMP_HW)) - return 2400; - case MT6370_CHG_TYPE_DCP: - if (IS_ENABLED(CONFIG_CHARGE_RAMP_SW) || - IS_ENABLED(CONFIG_CHARGE_RAMP_HW)) - /* A conservative value to prevent a bad charger. */ - return RT946X_AICR_TYP2MAX(2000); - case MT6370_CHG_TYPE_CDP: - case MT6370_CHG_TYPE_SAMSUNG_CHARGER: - return 1500; - case MT6370_CHG_TYPE_SDP: - default: - return USB_CHARGER_MIN_CURR_MA; - } -} - -static int rt946x_get_bc12_device_type(int charger_type) -{ - int reg; - - if (rt946x_read8(RT946X_REG_DPDM1, ®)) - return CHARGE_SUPPLIER_NONE; - - switch (reg & RT946X_MASK_BC12_TYPE) { - case RT946X_MASK_SDP: - return CHARGE_SUPPLIER_BC12_SDP; - case RT946X_MASK_CDP: - return CHARGE_SUPPLIER_BC12_CDP; - case RT946X_MASK_DCP: - return CHARGE_SUPPLIER_BC12_DCP; - default: - return CHARGE_SUPPLIER_NONE; - } -} - -static int rt946x_get_bc12_ilim(int charge_supplier) -{ - switch (charge_supplier) { - case CHARGE_SUPPLIER_BC12_DCP: - if (IS_ENABLED(CONFIG_CHARGE_RAMP_SW) || - IS_ENABLED(CONFIG_CHARGE_RAMP_HW)) - /* A conservative value to prevent a bad charger. */ - return RT946X_AICR_TYP2MAX(2000); - /* fallback */ - case CHARGE_SUPPLIER_BC12_CDP: - return 1500; - case CHARGE_SUPPLIER_BC12_SDP: - default: - return USB_CHARGER_MIN_CURR_MA; - } -} - -void rt946x_interrupt(enum gpio_signal signal) -{ - task_wake(TASK_ID_USB_CHG); -} - -int rt946x_toggle_bc12_detection(void) -{ - int rv; - rv = rt946x_enable_bc12_detection(0); - if (rv) - return rv; - /* mt6370 requires 40us delay to toggle RT946X_MASK_USBCHGEN */ - udelay(40); - return rt946x_enable_bc12_detection(1); -} - -#ifdef CONFIG_CHARGER_MT6370_BC12_GPIO -static void usb_pd_connect(void) -{ - rt946x_toggle_bc12_detection(); -} -DECLARE_HOOK(HOOK_USB_PD_CONNECT, usb_pd_connect, HOOK_PRIO_DEFAULT); -#endif - -static int rt946x_get_adc(enum rt946x_adc_in_sel adc_sel, int *adc_val) -{ - int rv, i, adc_start, adc_result = 0; - int adc_data_h, adc_data_l, aicr; - const int max_wait_times = 6; - - if (in_interrupt_context()) { - CPRINTS("Shouldn't use %s in IRQ", __func__); - return EC_ERROR_INVAL; - } - mutex_lock(&adc_access_lock); -#ifdef CONFIG_CHARGER_MT6370 - mt6370_enable_hidden_mode(1); -#endif - - /* Select ADC to desired channel */ - rv = rt946x_update_bits(RT946X_REG_CHGADC, RT946X_MASK_ADC_IN_SEL, - adc_sel << RT946X_SHIFT_ADC_IN_SEL); - if (rv) - goto out; - - if (adc_sel == MT6370_ADC_IBUS) { - rv = charger_get_input_current(&aicr); - if (rv) - goto out; - } - - /* Start ADC conversation */ - rv = rt946x_set_bit(RT946X_REG_CHGADC, RT946X_MASK_ADC_START); - if (rv) - goto out; - - for (i = 0; i < max_wait_times; i++) { - msleep(35); - rv = mt6370_pmu_reg_test_bit(RT946X_REG_CHGADC, - RT946X_SHIFT_ADC_START, - &adc_start); - if (!adc_start && rv == 0) - break; - } - if (i == max_wait_times) - CPRINTS("%s: wait conversation failed, sel = %d, rv = %d", - __func__, adc_sel, rv); - - /* Read ADC data */ - rv = rt946x_read8(RT946X_REG_ADCDATAH, &adc_data_h); - rv = rt946x_read8(RT946X_REG_ADCDATAL, &adc_data_l); - if (rv) - goto out; - -#if defined(CONFIG_CHARGER_RT9466) || defined(CONFIG_CHARGER_RT9467) - if (adc_sel == RT946X_ADC_VBUS_DIV5) - adc_result = ((adc_data_h << 8) | adc_data_l) * 25; - else - CPRINTS("%s: RT946X not yet support channels", __func__); - *adc_val = adc_result; -#elif defined(CONFIG_CHARGER_MT6370) - /* Calculate ADC value */ - adc_result = (adc_data_h * 256 + adc_data_l) - * mt6370_adc_unit[adc_sel] + mt6370_adc_offset[adc_sel]; - - /* For TS_BAT/TS_BUS, the real unit is 0.25, here we use 25(unit) */ - if (adc_sel == MT6370_ADC_TS_BAT) - adc_result /= 100; -#endif - -out: -#ifdef CONFIG_CHARGER_MT6370 - if (adc_sel == MT6370_ADC_IBUS) { - if (aicr < 400) /* 400mA */ - adc_result = adc_result * 67 / 100; - } - - if (adc_sel != MT6370_ADC_TS_BAT && adc_sel != MT6370_ADC_TEMP_JC) - *adc_val = adc_result / 1000; - else - *adc_val = adc_result; - mt6370_enable_hidden_mode(0); -#endif - mutex_unlock(&adc_access_lock); - return rv; -} - -int charger_get_vbus_voltage(int port) -{ - static int vbus_mv; - - rt946x_get_adc(RT946X_ADC_VBUS_DIV5, &vbus_mv); - return vbus_mv; -} - -#ifdef CONFIG_CHARGER_MT6370 -static int mt6370_toggle_cfo(void) -{ - int rv, data; - - rv = rt946x_read8(MT6370_REG_FLEDEN, &data); - if (rv) - return rv; - - if (data & MT6370_STROBE_EN_MASK) - return rv; - - /* read data */ - rv = rt946x_read8(RT946X_REG_CHGCTRL2, &data); - if (rv) - return rv; - - /* cfo off */ - data &= ~RT946X_MASK_CFO_EN; - rv = rt946x_write8(RT946X_REG_CHGCTRL2, data); - if (rv) - return rv; - - /* cfo on */ - data |= RT946X_MASK_CFO_EN; - return rt946x_write8(RT946X_REG_CHGCTRL2, data); -} - -static int mt6370_pmu_chg_mivr_irq_handler(void) -{ - int rv, ibus = 0, mivr_stat; - - rv = mt6370_pmu_reg_test_bit(MT6370_REG_CHGSTAT1, - MT6370_SHIFT_MIVR_STAT, &mivr_stat); - if (rv) - return rv; - - if (!mivr_stat) { - CPRINTS("%s: mivr stat not act", __func__); - return rv; - } - - rv = rt946x_get_adc(MT6370_ADC_IBUS, &ibus); - if (rv) - return rv; - - if (ibus < 100) /* 100mA */ - rv = mt6370_toggle_cfo(); - - return rv; -} - -static int mt6370_irq_handler(void) -{ - int data, mask, ret, reg_val; - int stat_chg, valid_chg, stat_old, stat_new; - - ret = rt946x_write8(MT6370_REG_IRQMASK, MT6370_IRQ_MASK_ALL); - if (ret) - return ret; - - ret = rt946x_read8(MT6370_REG_IRQIND, ®_val); - if (ret) - return ret; - - /* read stat before reading irq evt */ - ret = rt946x_read8(MT6370_REG_CHGSTAT1, &stat_old); - if (ret) - return ret; - - /* workaround for irq, divided irq event into upper and lower */ - ret = rt946x_read8(MT6370_REG_CHGIRQ1, &data); - if (ret) - return ret; - - /* read stat after reading irq evt */ - ret = rt946x_read8(MT6370_REG_CHGSTAT1, &stat_new); - if (ret) - return ret; - - ret = rt946x_read8(MT6370_REG_CHGMASK1, &mask); - if (ret) - return ret; - - ret = rt946x_write8(MT6370_REG_IRQMASK, 0x00); - if (ret) - return ret; - - stat_chg = stat_old ^ stat_new; - valid_chg = (stat_new & 0xF1) | (~stat_new & 0xF1); - data |= (stat_chg & valid_chg); - data &= ~mask; - if (data) - ret = mt6370_pmu_chg_mivr_irq_handler(); - return ret; -} -#endif /* CONFIG_CHARGER_MT6370 */ - -static void rt946x_bc12_workaround(void) -{ - /* - * There is a parasitic capacitance on D+, - * which results in pulling D+ up too slow while detecting BC1.2. - * So we try to fix this in two steps: - * 1. Pull D+ up to a voltage under 0.6V - * 2. re-toggling and pull D+ up to 0.6V (again) - * and then detect the voltage of D-. - */ - rt946x_toggle_bc12_detection(); - msleep(10); - rt946x_toggle_bc12_detection(); -} -DECLARE_DEFERRED(rt946x_bc12_workaround); - -void usb_charger_task(void *u) -{ - struct charge_port_info chg; - int bc12_type = CHARGE_SUPPLIER_NONE; - int chg_type; - int reg = 0; - int bc12_cnt = 0; - const int max_bc12_cnt = 3; - - chg.voltage = USB_CHARGER_VOLTAGE_MV; - while (1) { -#ifdef CONFIG_CHARGER_MT6370 - mt6370_irq_handler(); -#endif /* CONFIG_CHARGER_MT6370 */ - - rt946x_read8(RT946X_REG_DPDMIRQ, ®); - - /* VBUS attach event */ - if (reg & RT946X_MASK_DPDMIRQ_ATTACH) { - CPRINTS("VBUS attached: %dmV", - charger_get_vbus_voltage(0)); - if (IS_ENABLED(CONFIG_CHARGER_MT6370)) { - chg_type = mt6370_get_charger_type(); - bc12_type = - mt6370_get_bc12_device_type(chg_type); - chg.current = mt6370_get_bc12_ilim(bc12_type); - } else { - bc12_type = - rt946x_get_bc12_device_type(chg_type); - chg.current = rt946x_get_bc12_ilim(bc12_type); - } - CPRINTS("BC12 type %d", bc12_type); - if (bc12_type == CHARGE_SUPPLIER_NONE) - goto bc12_none; - if (IS_ENABLED(CONFIG_WIRELESS_CHARGER_P9221_R7) && - bc12_type == CHARGE_SUPPLIER_BC12_SDP && - wpc_chip_is_online()) { - p9221_notify_vbus_change(1); - CPRINTS("WPC ON"); - } - if (bc12_type == CHARGE_SUPPLIER_BC12_SDP && - ++bc12_cnt < max_bc12_cnt) { - /* - * defer the workaround and awaiting for - * waken up by the interrupt. - */ - hook_call_deferred( - &rt946x_bc12_workaround_data, 5); - goto wait_event; - } - - charge_manager_update_charge(bc12_type, 0, &chg); -bc12_none: - rt946x_enable_bc12_detection(0); - hook_notify(HOOK_AC_CHANGE); - } - - /* VBUS detach event */ - if (reg & RT946X_MASK_DPDMIRQ_DETACH) { - CPRINTS("VBUS detached"); - bc12_cnt = 0; -#ifdef CONFIG_WIRELESS_CHARGER_P9221_R7 - p9221_notify_vbus_change(0); -#endif - charge_manager_update_charge(bc12_type, 0, NULL); - - if (!IS_ENABLED(CONFIG_CHARGER_MT6370_BC12_GPIO)) - rt946x_enable_bc12_detection(1); - - hook_notify(HOOK_AC_CHANGE); - } - -wait_event: - task_wait_event(-1); - } -} - -int usb_charger_ramp_allowed(int supplier) -{ - return supplier == CHARGE_SUPPLIER_BC12_DCP; -} - -int usb_charger_ramp_max(int supplier, int sup_curr) -{ - return rt946x_get_bc12_ilim(supplier); -} -#endif /* HAS_TASK_USB_CHG */ - -/* Non-standard interface functions */ - -int rt946x_enable_charger_boost(int en) -{ - return (en ? rt946x_set_bit : rt946x_clr_bit) - (RT946X_REG_CHGCTRL2, RT946X_MASK_CHG_EN); -} - -/* - * rt946x reports VBUS ready after VBUS is up for ~500ms. - * Check if this works for the use case before calling this function. - */ -int rt946x_is_vbus_ready(void) -{ - int val = 0; - - return rt946x_read8(RT946X_REG_CHGSTATC, &val) ? - 0 : !!(val & RT946X_MASK_PWR_RDY); -} - -int rt946x_is_charge_done(void) -{ - int val = 0; - - if (rt946x_read8(RT946X_REG_CHGSTAT, &val)) - return 0; - - val = (val & RT946X_MASK_CHG_STAT) >> RT946X_SHIFT_CHG_STAT; - - return val == RT946X_CHGSTAT_DONE; -} - -int rt946x_cutoff_battery(void) -{ - int val = RT946X_MASK_SHIP_MODE; - -#ifdef CONFIG_CHARGER_MT6370 - val |= RT946X_MASK_TE | RT946X_MASK_CFO_EN | RT946X_MASK_CHG_EN; -#endif - return rt946x_set_bit(RT946X_REG_CHGCTRL2, val); -} - -int rt946x_enable_charge_termination(int en) -{ - return (en ? rt946x_set_bit : rt946x_clr_bit) - (RT946X_REG_CHGCTRL2, RT946X_MASK_TE); -} - -int rt946x_enable_charge_eoc(int en) -{ - return (en ? rt946x_set_bit : rt946x_clr_bit) - (RT946X_REG_CHGCTRL9, RT946X_MASK_EOC); -} - -#ifdef CONFIG_CHARGER_MT6370 -/* MT6370 LDO */ - -int mt6370_set_ldo_voltage(int mv) -{ - int rv; - int vout_val; - const int vout_mask = MT6370_MASK_LDOVOUT_EN | MT6370_MASK_LDOVOUT_VOUT; - - /* LDO output-off mode to floating. */ - rv = rt946x_update_bits(MT6370_REG_LDOCFG, MT6370_MASK_LDOCFG_OMS, 0); - if (rv) - return rv; - - /* Disable LDO if voltage is zero. */ - if (mv == 0) - return rt946x_clr_bit(MT6370_REG_LDOVOUT, - MT6370_MASK_LDOVOUT_EN); - - vout_val = 1 << MT6370_SHIFT_LDOVOUT_EN; - vout_val |= rt946x_closest_reg(MT6370_LDO_MIN, MT6370_LDO_MAX, - MT6370_LDO_STEP, mv); - return rt946x_update_bits(MT6370_REG_LDOVOUT, vout_mask, vout_val); -} - -/* MT6370 Display bias */ -int mt6370_db_external_control(int en) -{ - return rt946x_update_bits(MT6370_REG_DBCTRL1, MT6370_MASK_DB_EXT_EN, - en << MT6370_SHIFT_DB_EXT_EN); -} - -int mt6370_db_set_voltages(int vbst, int vpos, int vneg) -{ - int rv; - - /* set display bias VBST */ - rv = rt946x_update_bits(MT6370_REG_DBVBST, MT6370_MASK_DB_VBST, - rt946x_closest_reg(MT6370_DB_VBST_MIN, - MT6370_DB_VBST_MAX, - MT6370_DB_VBST_STEP, vbst)); - - /* set display bias VPOS */ - rv |= rt946x_update_bits(MT6370_REG_DBVPOS, MT6370_MASK_DB_VPOS, - rt946x_closest_reg(MT6370_DB_VPOS_MIN, - MT6370_DB_VPOS_MAX, - MT6370_DB_VPOS_STEP, vpos)); - - /* set display bias VNEG */ - rv |= rt946x_update_bits(MT6370_REG_DBVNEG, MT6370_MASK_DB_VNEG, - rt946x_closest_reg(MT6370_DB_VNEG_MIN, - MT6370_DB_VNEG_MAX, - MT6370_DB_VNEG_STEP, vneg)); - - /* Enable VNEG/VPOS discharge when VNEG/VPOS rails disabled. */ - rv |= rt946x_update_bits( - MT6370_REG_DBCTRL2, - MT6370_MASK_DB_VNEG_DISC | MT6370_MASK_DB_VPOS_DISC, - MT6370_MASK_DB_VNEG_DISC | MT6370_MASK_DB_VPOS_DISC); - - return rv; -} - -/* MT6370 BACKLIGHT LED */ - -int mt6370_backlight_set_dim(uint16_t dim) -{ - int rv; - - /* datasheet suggests that update BLDIM2 first then BLDIM */ - rv = rt946x_write8(MT6370_BACKLIGHT_BLDIM2, dim & MT6370_MASK_BLDIM2); - - if (rv) - return rv; - - rv = rt946x_write8(MT6370_BACKLIGHT_BLDIM, - (dim >> MT6370_SHIFT_BLDIM_MSB) & MT6370_MASK_BLDIM); - - return rv; -} - -/* MT6370 RGB LED */ - -int mt6370_led_set_dim_mode(enum mt6370_led_index index, - enum mt6370_led_dim_mode mode) -{ - if (index <= MT6370_LED_ID_OFF || index >= MT6370_LED_ID_COUNT) - return EC_ERROR_INVAL; - - rt946x_update_bits(MT6370_REG_RGBDIM_BASE + index, - MT6370_MASK_RGB_DIMMODE, - mode << MT6370_SHIFT_RGB_DIMMODE); - return EC_SUCCESS; -} - -int mt6370_led_set_color(uint8_t mask) -{ - return rt946x_update_bits(MT6370_REG_RGBEN, MT6370_MASK_RGB_ISNK_ALL_EN, - mask); -} - -int mt6370_led_set_brightness(enum mt6370_led_index index, uint8_t brightness) -{ - if (index >= MT6370_LED_ID_COUNT || index <= MT6370_LED_ID_OFF) - return EC_ERROR_INVAL; - - rt946x_update_bits(MT6370_REG_RGBISNK_BASE + index, - MT6370_MASK_RGBISNK_CURSEL, - brightness << MT6370_SHIFT_RGBISNK_CURSEL); - return EC_SUCCESS; -} - -int mt6370_led_set_pwm_dim_duty(enum mt6370_led_index index, uint8_t dim_duty) -{ - if (index >= MT6370_LED_ID_COUNT || index <= MT6370_LED_ID_OFF) - return EC_ERROR_INVAL; - - rt946x_update_bits(MT6370_REG_RGBDIM_BASE + index, - MT6370_MASK_RGB_DIMDUTY, - dim_duty << MT6370_SHIFT_RGB_DIMDUTY); - return EC_SUCCESS; -} - -int mt6370_led_set_pwm_frequency(enum mt6370_led_index index, - enum mt6370_led_pwm_freq freq) -{ - if (index >= MT6370_LED_ID_COUNT || index <= MT6370_LED_ID_OFF) - return EC_ERROR_INVAL; - - rt946x_update_bits(MT6370_REG_RGBISNK_BASE + index, - MT6370_MASK_RGBISNK_DIMFSEL, - freq << MT6370_SHIFT_RGBISNK_DIMFSEL); - return EC_SUCCESS; -} -#endif /* CONFIG_CHARGER_MT6370 */ diff --git a/driver/charger/rt946x.h b/driver/charger/rt946x.h deleted file mode 100644 index 9797e95255..0000000000 --- a/driver/charger/rt946x.h +++ /dev/null @@ -1,809 +0,0 @@ -/* Copyright 2017 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. - * - * Richtek rt9466/rt9467, Mediatek mt6370 battery charger driver. - */ - -#ifndef __CROS_EC_RT946X_H -#define __CROS_EC_RT946X_H - -/* Charger parameters */ -#define CHARGER_NAME RT946X_CHARGER_NAME -#define CHARGE_V_MAX 4710 -#define CHARGE_V_MIN 3900 -#define CHARGE_V_STEP 10 -#define CHARGE_I_MAX 5000 -#define CHARGE_I_MIN 100 -#define CHARGE_I_OFF 0 -#define CHARGE_I_STEP 100 -#define INPUT_I_MAX 3250 -#define INPUT_I_MIN 100 -#define INPUT_I_STEP 50 - -/* Registers for rt9466, rt9467 */ -#if defined(CONFIG_CHARGER_RT9466) || defined(CONFIG_CHARGER_RT9467) -#define RT946X_REG_CORECTRL0 0x00 -#define RT946X_REG_CORECTRL_RST RT946X_REG_CORECTRL0 -#define RT946X_REG_CHGCTRL1 0x01 -#define RT946X_REG_CHGCTRL2 0x02 -#define RT946X_REG_CHGCTRL3 0x03 -#define RT946X_REG_CHGCTRL4 0x04 -#define RT946X_REG_CHGCTRL5 0x05 -#define RT946X_REG_CHGCTRL6 0x06 -#define RT946X_REG_CHGCTRL7 0x07 -#define RT946X_REG_CHGCTRL8 0x08 -#define RT946X_REG_CHGCTRL9 0x09 -#define RT946X_REG_CHGCTRL10 0x0A -#define RT946X_REG_CHGCTRL11 0x0B -#define RT946X_REG_CHGCTRL12 0x0C -#define RT946X_REG_CHGCTRL13 0x0D -#define RT946X_REG_CHGCTRL14 0x0E -#define RT946X_REG_CHGCTRL15 0x0F -#define RT946X_REG_CHGCTRL16 0x10 -#define RT946X_REG_CHGADC 0x11 - -#ifdef CONFIG_CHARGER_RT9467 -#define RT946X_REG_DPDM1 0x12 -#define RT946X_REG_DPDM2 0x13 -#define RT946X_REG_DPDM3 0x14 -#endif - -#define RT946X_REG_CHGCTRL19 0x18 -#define RT946X_REG_CHGCTRL17 0x19 -#define RT946X_REG_CHGCTRL18 0x1A -#define RT946X_REG_CHGHIDDENCTRL2 0x21 -#define RT946X_REG_CHGHIDDENCTRL4 0x23 -#define RT946X_REG_CHGHIDDENCTRL6 0x25 -#define RT946X_REG_CHGHIDDENCTRL7 0x26 -#define RT946X_REG_CHGHIDDENCTRL8 0x27 -#define RT946X_REG_CHGHIDDENCTRL9 0x28 -#define RT946X_REG_CHGHIDDENCTRL15 0x2E -#define RT946X_REG_DEVICEID 0x40 -#define RT946X_REG_CHGSTAT 0x42 -#define RT946X_REG_CHGNTC 0x43 -#define RT946X_REG_ADCDATAH 0x44 -#define RT946X_REG_ADCDATAL 0x45 -#define RT946X_REG_CHGSTATC 0x50 -#define RT946X_REG_CHGFAULT 0x51 -#define RT946X_REG_TSSTATC 0x52 -#define RT946X_REG_CHGIRQ1 0x53 -#define RT946X_REG_CHGIRQ2 0x54 -#define RT946X_REG_CHGIRQ3 0x55 - -#ifdef CONFIG_CHARGER_RT9467 -#define RT946X_REG_DPDMIRQ 0x56 -#endif - -#define RT946X_REG_CHGSTATCCTRL 0x60 -#define RT946X_REG_CHGFAULTCTRL 0x61 -#define RT946X_REG_TSSTATCCTRL 0x62 -#define RT946X_REG_CHGIRQ1CTRL 0x63 -#define RT946X_REG_CHGIRQ2CTRL 0x64 -#define RT946X_REG_CHGIRQ3CTRL 0x65 - -#ifdef CONFIG_CHARGER_RT9467 -#define RT946X_REG_DPDMIRQCTRL 0x66 -#endif - -#elif defined(CONFIG_CHARGER_MT6370) -/* Registers for mt6370 */ -#define RT946X_REG_DEVICEID 0x00 -#define RT946X_REG_CORECTRL1 0x01 -#define RT946X_REG_CORECTRL2 0x02 -#define RT946X_REG_CORECTRL_RST RT946X_REG_CORECTRL2 -#define MT6370_REG_RSTPASCODE1 0x03 -#define MT6370_REG_RSTPASCODE2 0x04 -#define MT6370_REG_HIDDENPASCODE1 0x07 -#define MT6370_REG_HIDDENPASCODE2 0x08 -#define MT6370_REG_HIDDENPASCODE3 0x09 -#define MT6370_REG_HIDDENPASCODE4 0x0A -#define MT6370_REG_IRQIND 0x0B -#define MT6370_REG_IRQMASK 0x0C -#define MT6370_REG_OSCCTRL 0x10 -#define RT946X_REG_CHGCTRL1 0x11 -#define RT946X_REG_CHGCTRL2 0x12 -#define RT946X_REG_CHGCTRL3 0x13 -#define RT946X_REG_CHGCTRL4 0x14 -#define RT946X_REG_CHGCTRL5 0x15 -#define RT946X_REG_CHGCTRL6 0x16 -#define RT946X_REG_CHGCTRL7 0x17 -#define RT946X_REG_CHGCTRL8 0x18 -#define RT946X_REG_CHGCTRL9 0x19 -#define RT946X_REG_CHGCTRL10 0x1A -#define RT946X_REG_CHGCTRL11 0x1B -#define RT946X_REG_CHGCTRL12 0x1C -#define RT946X_REG_CHGCTRL13 0x1D -#define RT946X_REG_CHGCTRL14 0x1E -#define RT946X_REG_CHGCTRL15 0x1F -#define RT946X_REG_CHGCTRL16 0x20 -#define RT946X_REG_CHGADC 0x21 -#define MT6370_REG_DEVICETYPE 0x22 -#define RT946X_REG_DPDM1 MT6370_REG_DEVICETYPE -#define MT6370_REG_USBSTATUS1 0x27 -#define MT6370_REG_QCSTATUS2 0x29 -#define RT946X_REG_CHGCTRL17 0X2B -#define RT946X_REG_CHGCTRL18 0X2C -#define MT6370_REG_CHGHIDDENCTRL15 0x3E -#define RT946X_REG_CHGSTAT 0X4A -#define RT946X_REG_CHGNTC 0X4B -#define RT946X_REG_ADCDATAH 0X4C -#define RT946X_REG_ADCDATAL 0X4D -/* FLED */ -#define MT6370_REG_FLEDEN 0x7E -/* LDO */ -#define MT6370_REG_LDOCFG 0X80 -#define MT6370_REG_LDOVOUT 0X81 -/* RGB led */ -#define MT6370_REG_RGBDIM_BASE 0x81 -#define MT6370_REG_RGB1DIM 0x82 -#define MT6370_REG_RGB2DIM 0x83 -#define MT6370_REG_RGB3DIM 0x84 -#define MT6370_REG_RGBEN 0x85 -#define MT6370_REG_RGBISNK_BASE 0x85 -#define MT6370_REG_RGB1ISNK 0x86 -#define MT6370_REG_RGB2ISNK 0x87 -#define MT6370_REG_RGB3ISNK 0x88 -#define MT6370_REG_RGBCHRINDDIM 0x92 -#define MT6370_REG_RGBCHRINDCTRL 0x93 - -/* backlight */ -#define MT6370_BACKLIGHT_BLEN 0xA0 -#define MT6370_BACKLIGHT_BLPWM 0xA2 -#define MT6370_BACKLIGHT_BLDIM2 0xA4 -#define MT6370_BACKLIGHT_BLDIM 0xA5 - -/* Display bias */ -#define MT6370_REG_DBCTRL1 0XB0 -#define MT6370_REG_DBCTRL2 0XB1 -#define MT6370_REG_DBVBST 0XB2 -#define MT6370_REG_DBVPOS 0XB3 -#define MT6370_REG_DBVNEG 0XB4 -#define MT6370_REG_CHGIRQ1 0xC0 -#define RT946X_REG_DPDMIRQ 0xC6 - -/* status event */ -#define MT6370_REG_CHGSTAT1 0xD0 -#define RT946X_REG_CHGSTATC MT6370_REG_CHGSTAT1 -#define MT6370_REG_CHGSTAT2 0xD1 -#define RT946X_REG_CHGFAULT MT6370_REG_CHGSTAT2 -#define MT6370_REG_CHGSTAT3 0xD2 -#define MT6370_REG_CHGSTAT4 0xD3 -#define MT6370_REG_CHGSTAT5 0xD4 -#define MT6370_REG_CHGSTAT6 0xD5 -#define MT6370_REG_DPDMSTAT 0xD6 -#define MT6370_REG_DICHGSTAT 0xD7 -#define MT6370_REG_OVPCTRLSTAT 0xD8 -#define MT6370_REG_FLEDSTAT1 0xD9 -#define MT6370_REG_FLEDSTAT2 0xDA -#define MT6370_REG_BASESTAT 0xDB -#define MT6370_REG_LDOSTAT 0xDC -#define MT6370_REG_RGBSTAT 0xDD -#define MT6370_REG_BLSTAT 0xDE -#define MT6370_REG_DBSTAT 0xDF -/* irq mask */ -#define MT6370_REG_CHGMASK1 0xE0 -#define RT946X_REG_CHGSTATCCTRL MT6370_REG_CHGMASK1 -#define MT6370_REG_CHGMASK2 0xE1 -#define MT6370_REG_CHGMASK3 0xE2 -#define MT6370_REG_CHGMASK4 0xE3 -#define MT6370_REG_CHGMASK5 0xE4 -#define MT6370_REG_CHGMASK6 0xE5 -#define MT6370_REG_DPDMMASK1 0xE6 -#define MT6370_REG_DICHGMASK 0xE7 -#define MT6370_REG_OVPCTRLMASK 0xE8 -#define MT6370_REG_FLEDMASK1 0xE9 -#define MT6370_REG_FLEDMASK2 0xEA -#define MT6370_REG_BASEMASK 0xEB -#define MT6370_REG_LDOMASK 0xEC -#define MT6370_REG_RGBMASK 0xED -#define MT6370_REG_BLMASK 0xEE -#define MT6370_REG_DBMASK 0xEF -#else -#error "No suitable charger option defined" -#endif - -/* EOC current */ -#define RT946X_IEOC_MIN 100 -#define RT946X_IEOC_MAX 850 -#define RT946X_IEOC_STEP 50 - -/* Minimum Input Voltage Regulator */ -#define RT946X_MIVR_MIN 3900 -#define RT946X_MIVR_MAX 13400 -#define RT946X_MIVR_STEP 100 - -/* Boost voltage */ -#define RT946X_BOOST_VOLTAGE_MIN 4425 -#define RT946X_BOOST_VOLTAGE_MAX 5825 -#define RT946X_BOOST_VOLTAGE_STEP 25 - -/* IR compensation resistor */ -#define RT946X_IRCMP_RES_MIN 0 -#define RT946X_IRCMP_RES_MAX 175 -#define RT946X_IRCMP_RES_STEP 25 - -/* IR compensation voltage clamp */ -#define RT946X_IRCMP_VCLAMP_MIN 0 -#define RT946X_IRCMP_VCLAMP_MAX 224 -#define RT946X_IRCMP_VCLAMP_STEP 32 - -/* Pre-charge mode threshold voltage */ -#define RT946X_VPREC_MIN 2000 -#define RT946X_VPREC_MAX 3500 -#define RT946X_VPREC_STEP 100 - -/* Pre-charge current */ -#define RT946X_IPREC_MIN 100 -#define RT946X_IPREC_MAX 850 -#define RT946X_IPREC_STEP 50 - -/* AICLVTH */ -#define RT946X_AICLVTH_MIN 4100 -#define RT946X_AICLVTH_MAX 4800 -#define RT946X_AICLVTH_STEP 100 - -/* NTC */ -#define RT946X_BATTEMP_NORMAL 0x00 -#define RT946X_BATTEMP_WARM 0x02 -#define RT946X_BATTEMP_COOL 0x03 -#define RT946X_BATTEMP_COLD 0x05 -#define RT946X_BATTEMP_HOT 0x06 - -/* LDO voltage */ -#define MT6370_LDO_MIN 1600 -#define MT6370_LDO_MAX 4000 -#define MT6370_LDO_STEP 200 - -/* ========== CORECTRL0 0x00 ============ */ -#define RT946X_SHIFT_RST 7 -#define RT946X_SHIFT_CHG_RST 6 -#define RT946X_SHIFT_FLED_RST 5 -#define RT946X_SHIFT_LDO_RST 4 -#define RT946X_SHIFT_RGB_RST 3 -#define RT946X_SHIFT_BL_RST 2 -#define RT946X_SHIFT_DB_RST 1 -#define RT946X_SHIFT_REG_RST 0 - -#define RT946X_MASK_RST BIT(RT946X_SHIFT_RST) -#define RT946X_MASK_CHG_RST BIT(RT946X_SHIFT_CHG_RST) -#define RT946X_MASK_FLED_RST BIT(RT946X_SHIFT_FLED_RST) -#define RT946X_MASK_LDO_RST BIT(RT946X_SHIFT_LDO_RST) -#define RT946X_MASK_RGB_RST BIT(RT946X_SHIFT_RGB_RST) -#define RT946X_MASK_BL_RST BIT(RT946X_SHIFT_BL_RST) -#define RT946X_MASK_DB_RST BIT(RT946X_SHIFT_DB_RST) -#define RT946X_MASK_REG_RST BIT(RT946X_SHIFT_REG_RST) -#define RT946X_MASK_SOFT_RST \ - (RT946X_MASK_CHG_RST | RT946X_MASK_FLED_RST | RT946X_MASK_LDO_RST | \ - RT946X_MASK_RGB_RST | RT946X_MASK_BL_RST | RT946X_MASK_DB_RST | \ - RT946X_MASK_REG_RST) - -/* ========== CHGCTRL1 0x01 ============ */ -#define RT946X_SHIFT_OPA_MODE 0 -#define RT946X_SHIFT_HZ_EN 2 - -#define RT946X_MASK_OPA_MODE BIT(RT946X_SHIFT_OPA_MODE) -#define RT946X_MASK_HZ_EN BIT(RT946X_SHIFT_HZ_EN) - -/* ========== CHGCTRL2 0x02 ============ */ -#define RT946X_SHIFT_SHIP_MODE 7 -#define RT946X_SHIFT_TE 4 -#define RT946X_SHIFT_ILMTSEL 2 -#define RT946X_SHIFT_CFO_EN 1 -#define RT946X_SHIFT_CHG_EN 0 - -#define RT946X_MASK_SHIP_MODE BIT(RT946X_SHIFT_SHIP_MODE) -#define RT946X_MASK_TE BIT(RT946X_SHIFT_TE) -#define RT946X_MASK_ILMTSEL (0x3 << RT946X_SHIFT_ILMTSEL) -#define RT946X_MASK_CFO_EN BIT(RT946X_SHIFT_CFO_EN) -#define RT946X_MASK_CHG_EN BIT(RT946X_SHIFT_CHG_EN) - -/* ========== RSTPASCODE1 0x03 (mt6370) ============ */ -#define MT6370_MASK_RSTPASCODE1 0xA9 - -/* ========== CHGCTRL3 0x03 ============ */ -#define RT946X_SHIFT_AICR 2 -#define RT946X_SHIFT_ILIMEN 0 - -#define RT946X_MASK_AICR (0x3F << RT946X_SHIFT_AICR) -#define RT946X_MASK_ILIMEN BIT(RT946X_SHIFT_ILIMEN) - -/* - * The accuracy of AICR is 7%. So if AICR = 2150, - * then Max=2150, Typ=2000, Min=1860. And plus 25 since the AICR - * is 50ma a step. - */ -#define RT946X_AICR_TYP2MAX(x) ((x) * 107 / 100 + 25) - -/* ========== RSTPASCODE2 0x04 (mt6370) ============ */ -#define MT6370_MASK_RSTPASCODE2 0x96 - -/* ========== CHGCTRL4 0x04 ============ */ -#define RT946X_SHIFT_CV 1 - -#define RT946X_MASK_CV 0xFE - -/* ========== CHGCTRL5 0x05 ============ */ -#define RT946X_SHIFT_BOOST_VOLTAGE 2 - -#define RT946X_MASK_BOOST_VOLTAGE 0xFC - -/* ========== CHGCTRL6 0x06 ============ */ -#define RT946X_SHIFT_MIVR 1 - -#define RT946X_MASK_MIVR (0x7F << RT946X_SHIFT_MIVR) - -/* ========== CHGCTRL7 0x07 ============ */ -#define RT946X_SHIFT_ICHG 2 - -#define RT946X_MASK_ICHG (0x3F << RT946X_SHIFT_ICHG) - -/* ========== CHGCTRL8 0x08 ============ */ -#define RT946X_SHIFT_VPREC 4 -#define RT946X_SHIFT_IPREC 0 - -#define RT946X_MASK_VPREC (0xF << RT946X_SHIFT_VPREC) -#define RT946X_MASK_IPREC (0xF << RT946X_SHIFT_IPREC) - -/* ========== CHGCTRL9 0x09 ============ */ -#define RT946X_SHIFT_EOC 3 -#define RT946X_SHIFT_IEOC 4 - -#define RT946X_MASK_EOC BIT(RT946X_SHIFT_EOC) -#define RT946X_MASK_IEOC (0xF << RT946X_SHIFT_IEOC) - -/* ========== CHGCTRL10 0x0A ============ */ -#define RT946X_SHIFT_BOOST_CURRENT 0 - -#define RT946X_MASK_BOOST_CURRENT 0x07 - -/* ========== CHGCTRL12 0x0C ============ */ -#define RT946X_SHIFT_TMR_EN 1 -#define MT6370_IRQ_MASK_ALL 0xFE - -#define RT946X_MASK_TMR_EN BIT(RT946X_SHIFT_TMR_EN) - -/* ========== CHGCTRL13 0x0D ============ */ -#define RT946X_SHIFT_WDT_EN 7 - -#define RT946X_MASK_WDT_EN BIT(RT946X_SHIFT_WDT_EN) - -/* ========== CHGCTRL14 0x0E ============ */ -#define RT946X_SHIFT_AICLMEAS 7 -#define RT946X_SHIFT_AICLVTH 0 - -#define RT946X_MASK_AICLMEAS BIT(RT946X_SHIFT_AICLMEAS) -#define RT946X_MASK_AICLVTH 0x07 - -/* ========== CHGCTRL16 0x10 ============ */ -#define RT946X_SHIFT_JEITA_EN 4 - -#define RT946X_MASK_JEITA_EN BIT(RT946X_SHIFT_JEITA_EN) - -/* ========== CHGADC 0x11 ============ */ -#define RT946X_SHIFT_ADC_IN_SEL 4 -#define RT946X_SHIFT_ADC_START 0 - -#define RT946X_MASK_ADC_IN_SEL (0xF << RT946X_SHIFT_ADC_IN_SEL) -#define RT946X_MASK_ADC_START BIT(RT946X_SHIFT_ADC_START) - -/* ========== CHGDPDM1 0x12 (rt946x) DEVICETYPE 0x22 (mt6370) ============ */ -#define RT946X_SHIFT_USBCHGEN 7 -#define RT946X_SHIFT_DCDTIMEOUT 6 -#define RT946X_SHIFT_DCP 2 -#define RT946X_SHIFT_CDP 1 -#define RT946X_SHIFT_SDP 0 - -#define RT946X_MASK_USBCHGEN BIT(RT946X_SHIFT_USBCHGEN) -#define RT946X_MASK_DCDTIMEOUT BIT(RT946X_SHIFT_DCDTIMEOUT) -#define RT946X_MASK_DCP BIT(RT946X_SHIFT_DCP) -#define RT946X_MASK_CDP BIT(RT946X_SHIFT_CDP) -#define RT946X_MASK_SDP BIT(RT946X_SHIFT_SDP) - -#define RT946X_MASK_BC12_TYPE (RT946X_MASK_DCP | \ - RT946X_MASK_CDP | \ - RT946X_MASK_SDP) - -/* ========== USBSTATUS1 0x27 (mt6370) ============ */ -#define MT6370_SHIFT_DCD_TIMEOUT 2 -#define MT6370_SHIFT_USB_STATUS 4 - -#define MT6370_MASK_USB_STATUS 0x70 - -#define MT6370_CHG_TYPE_NOVBUS 0 -#define MT6370_CHG_TYPE_BUSY 1 -#define MT6370_CHG_TYPE_SDP 2 -#define MT6370_CHG_TYPE_SDPNSTD 3 -#define MT6370_CHG_TYPE_DCP 4 -#define MT6370_CHG_TYPE_CDP 5 -#define MT6370_CHG_TYPE_SAMSUNG_CHARGER 6 -#define MT6370_CHG_TYPE_APPLE_0_5A_CHARGER 7 -#define MT6370_CHG_TYPE_APPLE_1_0A_CHARGER 8 -#define MT6370_CHG_TYPE_APPLE_2_1A_CHARGER 9 -#define MT6370_CHG_TYPE_APPLE_2_4A_CHARGER 10 - -#define MT6370_MASK_DCD_TIMEOUT BIT(MT6370_SHIFT_DCD_TIMEOUT) - -/* ========== QCSTATUS2 0x29 (mt6370) ============ */ -#define MT6370_SHIFT_APP_OUT 5 -#define MT6370_SHIFT_SS_OUT 4 -#define MT6370_SHIFT_APP_REF 3 -#define MT6370_SHIFT_APP_DPDM_IN 2 -#define MT6370_SHIFT_APP_SS_PL 1 -#define MT6370_SHIFT_APP_SS_EN 0 - -#define MT6370_MASK_APP_OUT BIT(MT6370_SHIFT_APP_OUT) -#define MT6370_MASK_SS_OUT BIT(MT6370_SHIFT_SS_OUT) -#define MT6370_MASK_APP_REF BIT(MT6370_SHIFT_APP_REF) -#define MT6370_MASK_APP_DPDM_IN BIT(MT6370_SHIFT_APP_DPDM_IN) -#define MT6370_MASK_APP_SS_PL BIT(MT6370_SHIFT_APP_SS_PL) -#define MT6370_MASK_APP_SS_EN BIT(MT6370_SHIFT_APP_SS_EN) - -#define MT6360_MASK_CHECK_DPDM (MT6370_MASK_APP_SS_EN | \ - MT6370_MASK_APP_SS_PL | \ - MT6370_MASK_APP_DPDM_IN | \ - MT6370_MASK_APP_REF) - -/* ========== CHGCTRL18 0x1A ============ */ -#define RT946X_SHIFT_IRCMP_RES 3 -#define RT946X_SHIFT_IRCMP_VCLAMP 0 - -#define RT946X_MASK_IRCMP_RES (0x7 << RT946X_SHIFT_IRCMP_RES) -#define RT946X_MASK_IRCMP_VCLAMP (0x7 << RT946X_SHIFT_IRCMP_VCLAMP) - -/* ========== DEVICE_ID 0x40 ============ */ -#define RT946X_MASK_VENDOR_ID 0xF0 -#define RT946X_MASK_CHIP_REV 0x0F - -/* ========== CHGSTAT 0x42 ============ */ -#define RT946X_SHIFT_CHG_STAT 6 -#define RT946X_SHIFT_ADC_STAT 0 - -#define RT946X_MASK_CHG_STAT (0x3 << RT946X_SHIFT_CHG_STAT) -#define RT946X_MASK_ADC_STAT BIT(RT946X_SHIFT_ADC_STAT) - -/* ========== CHGNTC 0x43 ============ */ -#define RT946X_SHIFT_BATNTC_FAULT 4 - -#define RT946X_MASK_BATNTC_FAULT 0x70 - -/* ========== CHGSTATC 0x50 (rt946x) ============ */ -#define RT946X_SHIFT_PWR_RDY 7 - -#define RT946X_MASK_PWR_RDY BIT(RT946X_SHIFT_PWR_RDY) - -/* ========== CHGFAULT 0x51 (rt946x) ============ */ -#if defined(CONFIG_CHARGER_RT9466) || defined(CONFIG_CHARGER_RT9467) -#define RT946X_SHIFT_CHG_VSYSUV 4 -#define RT946X_SHIFT_CHG_VSYSOV 5 -#define RT946X_SHIFT_CHG_VBATOV 6 -#define RT946X_SHIFT_CHG_VBUSOV 7 - -#define RT946X_MASK_CHG_VSYSUV BIT(RT946X_SHIFT_CHG_VSYSUV) -#define RT946X_MASK_CHG_VSYSOV BIT(RT946X_SHIFT_CHG_VSYSOV) -#define RT946X_MASK_CHG_VBATOV BIT(RT946X_SHIFT_CHG_VBATOV) -#define RT946X_MASK_CHG_VBUSOV BIT(RT946X_SHIFT_CHG_VBUSOV) -#endif - -/* ========== DPDMIRQ 0x56 ============ */ -#if defined(CONFIG_CHARGER_RT9467) || defined(CONFIG_CHARGER_MT6370) -#define RT946X_SHIFT_DPDMIRQ_DETACH 1 -#define RT946X_SHIFT_DPDMIRQ_ATTACH 0 - -#define RT946X_MASK_DPDMIRQ_DETACH BIT(RT946X_SHIFT_DPDMIRQ_DETACH) -#define RT946X_MASK_DPDMIRQ_ATTACH BIT(RT946X_SHIFT_DPDMIRQ_ATTACH) -#endif - -/* ========== FLED EN 0x7E (mt6370) ============ */ -#define MT6370_STROBE_EN_MASK 0x04 - -/* ========== LDOCFG 0x80 (mt6370) ============ */ -#define MT6370_SHIFT_LDOCFG_OMS 6 - -#define MT6370_MASK_LDOCFG_OMS BIT(MT6370_SHIFT_LDOCFG_OMS) - -/* ========== LDOVOUT 0x81 (mt6370) ============ */ -#define MT6370_SHIFT_LDOVOUT_EN 7 -#define MT6370_SHIFT_LDOVOUT_VOUT 0 - -#define MT6370_MASK_LDOVOUT_EN BIT(MT6370_SHIFT_LDOVOUT_EN) -#define MT6370_MASK_LDOVOUT_VOUT (0xf << MT6370_SHIFT_LDOVOUT_VOUT) - -/* ========== RGBDIM 0x82/0x83/0x84 (mt6370) ============ */ -#define MT6370_LED_PWM_DIMDUTY_MIN 0x00 -#define MT6370_LED_PWM_DIMDUTY_MAX 0x1f - -#define MT6370_SHIFT_RGB_DIMMODE 5 -#define MT6370_SHIFT_RGB_DIMDUTY 0 - -#define MT6370_MASK_RGB_DIMMODE (3 << MT6370_SHIFT_RGB_DIMMODE) -#define MT6370_MASK_RGB_DIMDUTY (0x1f << MT6370_SHIFT_RGB_DIMDUTY) - -/* ========== RGBEN 0x85 (mt6370) ============ */ -#define MT6370_SHIFT_RGB_ISNK1DIM 7 -#define MT6370_SHIFT_RGB_ISNK2DIM 6 -#define MT6370_SHIFT_RGB_ISNK3DIM 5 -#define MT6370_SHIFT_RGB_ISNKDIM_BASE 8 - -#define MT6370_MASK_RGB_ISNK1DIM_EN BIT(MT6370_SHIFT_RGB_ISNK1DIM) -#define MT6370_MASK_RGB_ISNK2DIM_EN BIT(MT6370_SHIFT_RGB_ISNK2DIM) -#define MT6370_MASK_RGB_ISNK3DIM_EN BIT(MT6370_SHIFT_RGB_ISNK3DIM) -#define MT6370_MASK_RGB_ISNK_ALL_EN (MT6370_MASK_RGB_ISNK1DIM_EN | \ - MT6370_MASK_RGB_ISNK2DIM_EN | \ - MT6370_MASK_RGB_ISNK3DIM_EN) - -/* ========== RGB_ISNK 0x86/0x87/0x88 (mt6370) ============ */ -#define MT6370_LED_BRIGHTNESS_MIN 0 -#define MT6370_LED_BRIGHTNESS_MAX 7 - -#define MT6370_SHIFT_RGBISNK_CURSEL 0 -#define MT6370_SHIFT_RGBISNK_DIMFSEL 3 -#define MT6370_MASK_RGBISNK_CURSEL (0x7 << MT6370_SHIFT_RGBISNK_CURSEL) -#define MT6370_MASK_RGBISNK_DIMFSEL (0x7 << MT6370_SHIFT_RGBISNK_DIMFSEL) - -/* ========== DBCTRL1 (mt6370) ============ */ -#define MT6370_SHIFT_DB_EXT_EN 0 -#define MT6370_SHIFT_DB_PERIODIC_FIX 4 -#define MT6370_SHIFT_DB_SINGLE_PIN 5 -#define MT6370_SHIFT_DB_FREQ_PM 6 -#define MT6370_SHIFT_DB_PERIODIC_MODE 7 - -#define MT6370_MASK_DB_EXT_EN 1 -#define MT6370_MASK_DB_PERIODIC_FIX 1 -#define MT6370_MASK_DB_SINGLE_PIN 1 -#define MT6370_MASK_DB_FREQ_PM 1 -#define MT6370_MASK_DB_PERIODIC_MODE 1 - -/* ========== DBCTRL1 (mt6370) ============ */ -#define MT6370_MASK_DB_VNEG_DISC BIT(2) -#define MT6370_MASK_DB_VPOS_DISC BIT(5) - -/* ========== DBVBST (mt6370) ============ */ -#define MT6370_SHIFT_DB_VBST 0 - -#define MT6370_MASK_DB_VBST 0x3f - -#define MT6370_DB_VBST_MAX 6200 -#define MT6370_DB_VBST_MIN 4000 -#define MT6370_DB_VBST_STEP 50 - -/* ========== DBVPOS (mt6370) ============ */ -#define MT6370_SHIFT_DB_VPOS 0 - -#define MT6370_MASK_DB_VPOS 0x3f - -#define MT6370_DB_VPOS_MAX 6000 -#define MT6370_DB_VPOS_MIN 4000 -#define MT6370_DB_VPOS_STEP 50 - -/* ========== DBVNEG (mt6370) ============ */ -#define MT6370_SHIFT_DB_VNEG 0 - -#define MT6370_MASK_DB_VNEG 0x3f - -#define MT6370_DB_VNEG_MAX 6000 -#define MT6370_DB_VNEG_MIN 4000 -#define MT6370_DB_VNEG_STEP 50 - -/* ========== BLEN 0xA0 (mt6370) ============ */ -#define MT6370_SHIFT_BLED_EXT_EN 7 -#define MT6370_SHIFT_BLED_EN 6 -#define MT6370_SHIFT_BLED_1CH_EN 5 -#define MT6370_SHIFT_BLED_2CH_EN 4 -#define MT6370_SHIFT_BLED_3CH_EN 3 -#define MT6370_SHIFT_BLED_4CH_EN 2 -#define MT6370_SHIFT_BLED_CODE 1 -#define MT6370_SHIFT_BLED_CONFIG 0 - -#define MT6370_MASK_BLED_EXT_EN BIT(MT6370_SHIFT_BLED_EXT_EN) -#define MT6370_MASK_BLED_EN BIT(MT6370_SHIFT_BLED_EN) -#define MT6370_MASK_BLED_1CH_EN BIT(MT6370_SHIFT_BLED_1CH_EN) -#define MT6370_MASK_BLED_2CH_EN BIT(MT6370_SHIFT_BLED_2CH_EN) -#define MT6370_MASK_BLED_3CH_EN BIT(MT6370_SHIFT_BLED_3CH_EN) -#define MT6370_MASK_BLED_4CH_EN BIT(MT6370_SHIFT_BLED_4CH_EN) - -#define MT6370_BLED_CODE_LINEAR BIT(MT6370_SHIFT_BLED_CODE) -#define MT6370_BLED_CODE_EXP 0 - -#define MT6370_BLED_CONFIG_ACTIVE_HIGH BIT(MT6370_SHIFT_BLED_CONFIG) -#define MT6370_BLED_CONFIG_ACTIVE_LOW 0 - -/* ========== BLPWM 0xA2 (mt6370) ============ */ -#define MT6370_SHIFT_BLPWM_BLED_PWM 7 - -#define MT6370_MASK_BLPWM_BLED_PWM BIT(MT6370_SHIFT_BLPWM_BLED_PWM) - -/* ========== BLDIM2 0xA4 (mt6370) ============ */ -#define MT6370_MASK_BLDIM2 0x7 - -/* ========== BLDIM 0xA5 (mt6370) ============ */ -#define MT6370_SHIFT_BLDIM_MSB 3 -#define MT6370_MASK_BLDIM 0xff - -#define MT6370_BLDIM_DEFAULT 0x7ff - -/* ========== CHG_IRQ1 0xC0 (mt6370) ============ */ -#define MT6370_SHIFT_MIVR_EVT 6 -#define MT6370_MASK_MIVR_EVT BIT(MT6370_SHIFT_MIVR_EVT) - -/* ========== CHGSTAT2 0xD0 (mt6370) ============ */ -#define MT6370_SHIFT_MIVR_STAT 6 - -/* ========== CHGSTAT2 0xD1 (mt6370) ============ */ -#ifdef CONFIG_CHARGER_MT6370 -#define MT6370_SHIFT_CHG_VBUSOV_STAT 7 -#define MT6370_SHIFT_CHG_VBATOV_STAT 6 - -#define RT946X_MASK_CHG_VBATOV MT6370_SHIFT_CHG_VBATOV_STAT - -#define MT6370_MASK_CHG_VBUSOV_STAT BIT(MT6370_SHIFT_CHG_VBUSOV_STAT) -#define MT6370_MASK_CHG_VBATOV_STAT BIT(MT6370_SHIFT_CHG_VBATOV_STAT) -#endif - -/* ADC unit/offset */ -#define MT6370_ADC_UNIT_VBUS_DIV5 25000 /* uV */ -#define MT6370_ADC_UNIT_VBUS_DIV2 10000 /* uV */ -#define MT6370_ADC_UNIT_VSYS 5000 /* uV */ -#define MT6370_ADC_UNIT_VBAT 5000 /* uV */ -#define MT6370_ADC_UNIT_TS_BAT 25 /* 0.01% */ -#define MT6370_ADC_UNIT_IBUS 50000 /* uA */ -#define MT6370_ADC_UNIT_IBAT 50000 /* uA */ -#define MT6370_ADC_UNIT_CHG_VDDP 5000 /* uV */ -#define MT6370_ADC_UNIT_TEMP_JC 2 /* degree */ - -#define MT6370_ADC_OFFSET_VBUS_DIV5 0 /* mV */ -#define MT6370_ADC_OFFSET_VBUS_DIV2 0 /* mV */ -#define MT6370_ADC_OFFSET_VSYS 0 /* mV */ -#define MT6370_ADC_OFFSET_VBAT 0 /* mV */ -#define MT6370_ADC_OFFSET_TS_BAT 0 /* % */ -#define MT6370_ADC_OFFSET_IBUS 0 /* mA */ -#define MT6370_ADC_OFFSET_IBAT 0 /* mA */ -#define MT6370_ADC_OFFSET_CHG_VDDP 0 /* mV */ -#define MT6370_ADC_OFFSET_TEMP_JC (-40) /* degree */ - -/* ========== Variant-specific configuration ============ */ -#if defined(CONFIG_CHARGER_RT9466) - #define RT946X_CHARGER_NAME "rt9466" - #define RT946X_VENDOR_ID 0x80 - #define RT946X_ADDR_FLAGS 0x53 -#elif defined(CONFIG_CHARGER_RT9467) - #define RT946X_CHARGER_NAME "rt9467" - #define RT946X_VENDOR_ID 0x90 - #define RT946X_ADDR_FLAGS 0x5B -#elif defined(CONFIG_CHARGER_MT6370) - #define RT946X_CHARGER_NAME "mt6370" - #define RT946X_VENDOR_ID 0xE0 - #define RT946X_ADDR_FLAGS 0x34 -#else - #error "No suitable charger option defined" -#endif - -/* RT946x specific interface functions */ - -/* Power on reset */ -int rt946x_por_reset(void); - -/* Interrupt handler for rt946x */ -void rt946x_interrupt(enum gpio_signal signal); - -/* Enable/Disable rt946x (in charger or boost mode) */ -int rt946x_enable_charger_boost(int en); - -/* - * Return 1 if VBUS is ready, which means - * UVLO < VBUS < VOVP && VBUS > BATS + VSLP - */ -int rt946x_is_vbus_ready(void); - -/* Return 1 if rt946x triggers charge termination due to full charge. */ -int rt946x_is_charge_done(void); - -/* - * Cut off the battery (force BATFET to turn off). - * Return 0 if it succeeds. - */ -int rt946x_cutoff_battery(void); - -/* Enable/Disable charge temination */ -int rt946x_enable_charge_termination(int en); - -/* Enable/Disable charge EOC */ -int rt946x_enable_charge_eoc(int en); - -/** - * Toggle BC12 detection - * - * @return EC_SUCCESS or EC_ERROR_* - */ -int rt946x_toggle_bc12_detection(void); - -struct rt946x_init_setting { - uint16_t eoc_current; - uint16_t mivr; - uint16_t ircmp_vclamp; - uint16_t ircmp_res; - uint16_t boost_voltage; - uint16_t boost_current; -}; - -#ifdef CONFIG_CHARGER_MT6370 - -/* - * Set LDO voltage. - * Disable LDO if voltage is zero. - */ -int mt6370_set_ldo_voltage(int mv); - -enum mt6370_led_index { - MT6370_LED_ID_OFF = 0, - MT6370_LED_ID1 = 1, - MT6370_LED_ID2 = 2, - MT6370_LED_ID3 = 3, - MT6370_LED_ID_COUNT, /* The bound of the ID indexes. */ -}; - -enum mt6370_led_dim_mode { - MT6370_LED_DIM_MODE_PWM = 0, - MT6370_LED_DIM_MODE_BREATH = 1, - MT6370_LED_DIM_MODE_REGISTER = 3 -}; - -enum mt6370_led_pwm_freq { - MT6370_LED_PWM_FREQ01 = 0, /* 0.1 Hz */ - MT6370_LED_PWM_FREQ02 = 1, /* 0.2 Hz */ - MT6370_LED_PWM_FREQ05 = 2, /* 0.5 Hz */ - MT6370_LED_PWM_FREQ1 = 3, /* 1 Hz */ - MT6370_LED_PWM_FREQ2 = 4, /* 2 Hz */ - MT6370_LED_PWM_FREQ5 = 5, /* 5 Hz */ - MT6370_LED_PWM_FREQ200 = 6, /* 200 Hz */ - MT6370_LED_PWM_FREQ1000 = 7 /* 1000 Hz */ -}; - -/* Enable display bias external pin control. */ -int mt6370_db_external_control(int en); - -/** - * Set backlight LED dim. - * - * dim: A value from 0 to 2047. - * return: EC_SUCCESS on success, and EC_ERROR_* otherwise. - */ -int mt6370_backlight_set_dim(uint16_t dim); - -/** - * MT6370 display bias voltage settings. - * - * Set disaply bias voltages for the panel. - * - * vbst: VBST config in mv. - * vpos: VPOS config in mv. - * vneg: VNEG config in mv. - * return: EC_SUCCESS on succes, and EC_ERROR_* otherwise. - */ -int mt6370_db_set_voltages(int vbst, int vpos, int vneg); - -/* Set LED brightness */ -int mt6370_led_set_brightness(enum mt6370_led_index index, uint8_t brightness); - -/** - * Set LED Color - * - * mask: Bitmap indicating 1=on 0=off for each LED. 000 = all off. - * Combination of MT6370_MASK_RGB_ISNK1/2/3DIM_EN. - * return: EC_SUCCESS or EC_ERROR_* on error. - */ -int mt6370_led_set_color(uint8_t mask); - -/* Set LED dim mode, available modes: REGISTER, PWM, BREATH. */ -int mt6370_led_set_dim_mode(enum mt6370_led_index index, - enum mt6370_led_dim_mode mode); - -/* Set LED PWM mode duty */ -int mt6370_led_set_pwm_dim_duty(enum mt6370_led_index index, uint8_t dim_duty); - -/* Set LED PWM mode frequency */ -int mt6370_led_set_pwm_frequency(enum mt6370_led_index index, - enum mt6370_led_pwm_freq freq); -#endif - -#endif /* __CROS_EC_RT946X_H */ diff --git a/driver/charger/sy21612.c b/driver/charger/sy21612.c deleted file mode 100644 index 0a1b122d28..0000000000 --- a/driver/charger/sy21612.c +++ /dev/null @@ -1,214 +0,0 @@ -/* Copyright 2017 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. - * - * SILERGY SY21612 buck-boost converter driver. - */ - - -#include "console.h" -#include "hooks.h" -#include "i2c.h" -#include "sy21612.h" -#include "task.h" -#include "util.h" - -/* Console output macros */ -#define CPUTS(outstr) cputs(CC_CHARGER, outstr) -#define CPRINTF(format, args...) cprintf(CC_CHARGER, format, ## args) -#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ## args) - -static int sy21612_clear_set_reg(int reg, int clear, int set) -{ - int val, old_val, rv; - - rv = i2c_read8(I2C_PORT_SY21612, SY21612_ADDR_FLAGS, reg, &old_val); - if (rv) - return rv; - - val = old_val; - val &= ~clear; - val |= set; - - if (val != old_val || clear || set) - rv = i2c_write8(I2C_PORT_SY21612, SY21612_ADDR_FLAGS, - reg, val); - - return rv; -} - -static int sy21612_read(int reg, int *val) -{ - return i2c_read8(I2C_PORT_SY21612, SY21612_ADDR_FLAGS, reg, val); -} - -int sy21612_enable_regulator(int enable) -{ - return enable ? - sy21612_clear_set_reg(SY21612_CTRL1, 0, SY21612_CTRL1_REG_EN) : - sy21612_clear_set_reg(SY21612_CTRL1, SY21612_CTRL1_REG_EN, 0); -} - -int sy21612_enable_adc(int enable) -{ - return enable ? - sy21612_clear_set_reg(SY21612_CTRL1, 0, SY21612_CTRL1_ADC_EN) : - sy21612_clear_set_reg(SY21612_CTRL1, SY21612_CTRL1_ADC_EN, 0); -} - -int sy21612_set_adc_mode(int auto_mode) -{ - return auto_mode ? - sy21612_clear_set_reg(SY21612_CTRL1, - 0, SY21612_CTRL1_ADC_AUTO_MODE) : - sy21612_clear_set_reg(SY21612_CTRL1, - SY21612_CTRL1_ADC_AUTO_MODE, 0); -} - -int sy21612_set_vbus_discharge(int auto_discharge) -{ - return auto_discharge ? - sy21612_clear_set_reg(SY21612_CTRL1, - SY21612_CTRL1_VBUS_NDISCHG, 0) : - sy21612_clear_set_reg(SY21612_CTRL1, - 0, SY21612_CTRL1_VBUS_NDISCHG); -} - -int sy21612_set_switching_freq(enum sy21612_switching_freq freq) -{ - return sy21612_clear_set_reg(SY21612_CTRL2, - SY21612_CTRL2_FREQ_MASK, - freq << SY21612_CTRL2_FREQ_SHIFT); -} - -int sy21612_set_vbus_volt(enum sy21612_vbus_volt volt) -{ - return sy21612_clear_set_reg(SY21612_CTRL2, - SY21612_CTRL2_VBUS_MASK, - volt << SY21612_CTRL2_VBUS_SHIFT); -} - -int sy21612_set_vbus_adj(enum sy21612_vbus_adj adj) -{ - return sy21612_clear_set_reg(SY21612_CTRL2, - SY21612_CTRL2_VBUS_ADJ_MASK, - adj << SY21612_CTRL2_VBUS_ADJ_SHIFT); -} - -int sy21612_set_sink_mode(int sink_mode) -{ - return sink_mode ? - sy21612_clear_set_reg(SY21612_PROT2, - 0, SY21612_PROT2_SINK_MODE) : - sy21612_clear_set_reg(SY21612_PROT2, - SY21612_PROT2_SINK_MODE, 0); -} - -int sy21612_is_power_good(void) -{ - int reg; - - if (sy21612_read(SY21612_STATE, ®)) - return 0; - - return reg & SY21612_STATE_POWER_GOOD; -} - -int sy21612_read_clear_int(void) -{ - int reg; - - if (sy21612_read(SY21612_INT, ®)) - return 0; - - return reg; -} - -int sy21612_get_vbat_voltage(void) -{ - int reg; - - if (sy21612_read(SY21612_VBAT_VOLT, ®)) - return 0; - - return reg * 25000 / 255; -} - -int sy21612_get_vbus_voltage(void) -{ - int reg; - - if (sy21612_read(SY21612_VBUS_VOLT, ®)) - return 0; - - return reg * 25000 / 255; -} - -int sy21612_get_vbus_current(void) -{ - int reg; - - if (sy21612_read(SY21612_VBUS_CURRENT, ®)) - return 0; - - /* - * delta V in range 0 ~ 67mV - * sense resistor 10 mOhm - */ - return reg * 6700 / 255; -} - -void sy21612_int(enum gpio_signal signal) -{ -#ifdef HAS_TASK_SY21612 - task_wake(TASK_ID_SY21612); -#endif -} - -#ifdef HAS_TASK_SY21612 -void sy21612_task(void) -{ - int flags; - - while (1) { - task_wait_event(-1); - if (sy21612_read(SY21612_INT, &flags)) - continue; - /* TODO: notify the error condition and enable regulator */ - if (flags & SY21612_INT_VBUS_OCP) - CPUTS("buck-boost VBUS OCP\n"); - if (flags & SY21612_INT_INDUCTOR_OCP) - CPUTS("buck-boost inductor OCP\n"); - if (flags & SY21612_INT_UVP) - CPUTS("buck-boost UVP\n"); - if (flags & SY21612_INT_OTP) - CPUTS("buck-boost OTP\n"); - } -} -#endif - -#ifdef CONFIG_CMD_CHARGER -static int command_sy21612(int argc, char **argv) -{ - int i, val, rv; - - ccputs("sy21612 regs:\n"); - for (i = 0; i < 9; i++) { - ccprintf("[%02x] ", i); - rv = sy21612_read(i, &val); - if (rv) - ccprintf(" x (%d)\n", rv); - else - ccprintf("%02x - %pb\n", val, BINARY_VALUE(val, 8)); - } - - ccprintf("vbat voltage: %d mV\n", sy21612_get_vbat_voltage()); - ccprintf("vbus voltage: %d mV\n", sy21612_get_vbus_voltage()); - ccprintf("vbus current: %d mA\n", sy21612_get_vbus_current()); - - return 0; -} -DECLARE_CONSOLE_COMMAND(sy21612, command_sy21612, - NULL, NULL); -#endif - diff --git a/driver/charger/sy21612.h b/driver/charger/sy21612.h deleted file mode 100644 index befb8e6a35..0000000000 --- a/driver/charger/sy21612.h +++ /dev/null @@ -1,164 +0,0 @@ -/* Copyright 2017 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. - * - * SILERGY SY21612 buck-boost converter driver. - */ - -#ifndef __CROS_EC_SY21612_H -#define __CROS_EC_SY21612_H - -#include "gpio.h" - -#ifndef SY21612_ADDR_FLAGS -#define SY21612_ADDR_FLAGS 0x71 -#endif - -enum sy21612_switching_freq { - SY21612_FREQ_250KHZ = 0, - SY21612_FREQ_500KHZ, - SY21612_FREQ_750KHZ, - SY21612_FREQ_1MHZ -}; - -enum sy21612_vbus_volt { - SY21612_VBUS_5V = 2, - SY21612_VBUS_7V, - SY21612_VBUS_9V, - SY21612_VBUS_12V, - SY21612_VBUS_15V, - SY21612_VBUS_20V, -}; - -enum sy21612_vbus_adj { - SY21612_VBUS_M2_5 = 0, - SY21612_VBUS_M1_25, - SY21612_VBUS_0, - SY21612_VBUS_1_25, - SY21612_VBUS_2_5, - SY21612_VBUS_3_75, - SY21612_VBUS_5, -}; - -#define SY21612_CTRL1 0x00 -#define SY21612_CTRL1_REG_EN BIT(7) -#define SY21612_CTRL1_LOW_BAT_MASK (7 << 4) -#define SY21612_CTRL1_LOW_BAT_10_2V (0 << 4) -#define SY21612_CTRL1_LOW_BAT_10_7V BIT(4) -#define SY21612_CTRL1_LOW_BAT_11_2V (2 << 4) -#define SY21612_CTRL1_LOW_BAT_11_7V (3 << 4) -#define SY21612_CTRL1_LOW_BAT_22_0V (4 << 4) -#define SY21612_CTRL1_LOW_BAT_22_5V (5 << 4) -#define SY21612_CTRL1_LOW_BAT_23_0V (6 << 4) -#define SY21612_CTRL1_LOW_BAT_23_5V (7 << 4) -#define SY21612_CTRL1_ADC_EN BIT(3) -#define SY21612_CTRL1_ADC_AUTO_MODE BIT(2) -#define SY21612_CTRL1_VBUS_NDISCHG BIT(1) - -#define SY21612_CTRL2 0x01 -#define SY21612_CTRL2_FREQ_MASK (3 << 6) -#define SY21612_CTRL2_FREQ_SHIFT 6 -#define SY21612_CTRL2_FREQ_250K (0 << 6) -#define SY21612_CTRL2_FREQ_500K BIT(6) -#define SY21612_CTRL2_FREQ_750K (2 << 6) -#define SY21612_CTRL2_FREQ_1M (3 << 6) -#define SY21612_CTRL2_VBUS_MASK (7 << 3) -#define SY21612_CTRL2_VBUS_SHIFT 3 -#define SY21612_CTRL2_VBUS_5V (2 << 3) -#define SY21612_CTRL2_VBUS_7V (3 << 3) -#define SY21612_CTRL2_VBUS_9V (4 << 3) -#define SY21612_CTRL2_VBUS_12V (5 << 3) -#define SY21612_CTRL2_VBUS_15V (6 << 3) -#define SY21612_CTRL2_VBUS_20V (7 << 3) -#define SY21612_CTRL2_VBUS_ADJ_MASK 7 -#define SY21612_CTRL2_VBUS_ADJ_SHIFT 0 -#define SY21612_CTRL2_VBUS_ADJ_M2_5 0 -#define SY21612_CTRL2_VBUS_ADJ_M1_25 1 -#define SY21612_CTRL2_VBUS_ADJ_0 2 -#define SY21612_CTRL2_VBUS_ADJ_1_25 3 -#define SY21612_CTRL2_VBUS_ADJ_2_5 4 -#define SY21612_CTRL2_VBUS_ADJ_3_75 5 -#define SY21612_CTRL2_VBUS_ADJ_5 6 - -#define SY21612_PROT1 0x02 -#define SY21612_PROT1_I_THRESH_MASK (7 << 5) -#define SY21612_PROT1_I_THRESH_18MV (0 << 5) -#define SY21612_PROT1_I_THRESH_22MV BIT(5) -#define SY21612_PROT1_I_THRESH_27MV (2 << 5) -#define SY21612_PROT1_I_THRESH_31MV (3 << 5) -#define SY21612_PROT1_I_THRESH_36MV (4 << 5) -#define SY21612_PROT1_I_THRESH_45MV (5 << 5) -#define SY21612_PROT1_I_THRESH_54MV (6 << 5) -#define SY21612_PROT1_I_THRESH_64MV (7 << 5) -#define SY21612_PROT1_OVP_THRESH_MASK (3 << 3) -#define SY21612_PROT1_OVP_THRESH_110 (0 << 3) -#define SY21612_PROT1_OVP_THRESH_115 BIT(3) -#define SY21612_PROT1_OVP_THRESH_120 (2 << 3) -#define SY21612_PROT1_OVP_THRESH_125 (3 << 3) -#define SY21612_PROT1_UVP_THRESH_MASK (3 << 1) -#define SY21612_PROT1_UVP_THRESH_50 (0 << 1) -#define SY21612_PROT1_UVP_THRESH_60 BIT(1) -#define SY21612_PROT1_UVP_THRESH_70 (2 << 1) -#define SY21612_PROT1_UVP_THRESH_80 (3 << 1) - -#define SY21612_PROT2 0x03 -#define SY21612_PROT2_I_LIMIT_MASK (3 << 6) -#define SY21612_PROT2_I_LIMIT_6A (0 << 6) -#define SY21612_PROT2_I_LIMIT_8A (2 << 6) -#define SY21612_PROT2_I_LIMIT_10A (3 << 6) -#define SY21612_PROT2_OCP_AUTORECOVER BIT(5) -#define SY21612_PROT2_UVP_AUTORECOVER BIT(4) -#define SY21612_PROT2_OTP_AUTORECOVER BIT(3) -#define SY21612_PROT2_SINK_MODE BIT(2) - -#define SY21612_STATE 0x04 -#define SY21612_STATE_POWER_GOOD BIT(7) -#define SY21612_STATE_VBAT_LT_VBUS BIT(6) -#define SY21612_STATE_VBAT_LOW BIT(5) - -#define SY21612_INT 0x05 -#define SY21612_INT_ADC_READY BIT(7) -#define SY21612_INT_VBUS_OCP BIT(6) -#define SY21612_INT_INDUCTOR_OCP BIT(5) -#define SY21612_INT_UVP BIT(4) -#define SY21612_INT_OTP BIT(3) - -/* Battery voltage range: 0 ~ 25V */ -#define SY21612_VBAT_VOLT 0x06 - -/* VBUS voltage range: 0 ~ 25V */ -#define SY21612_VBUS_VOLT 0x07 - -/* Output current sense voltage range 0 ~ 67mV */ -#define SY21612_VBUS_CURRENT 0x08 - -/* Enable or disable the regulator */ -int sy21612_enable_regulator(int enable); -/* Enable internal adc */ -int sy21612_enable_adc(int enable); -/* Set ADC mode to single or auto */ -int sy21612_set_adc_mode(int auto_mode); -/* Enable VBUS auto discharge when regulator is disabled */ -int sy21612_set_vbus_discharge(int auto_discharge); -/* Set buck-boost switching frequency */ -int sy21612_set_switching_freq(enum sy21612_switching_freq freq); -/* Set VBUS output voltage */ -int sy21612_set_vbus_volt(enum sy21612_vbus_volt volt); -/* Adjust VBUS output voltage */ -int sy21612_set_vbus_adj(enum sy21612_vbus_adj adj); -/* Set bidirection mode */ -int sy21612_set_sink_mode(int sink_mode); -/* Get power good status */ -int sy21612_is_power_good(void); -/* Read and clear interrupt flags */ -int sy21612_read_clear_int(void); -/* Get VBUS voltage in mV */ -int sy21612_get_vbat_voltage(void); -/* Get VBUS voltage in mV */ -int sy21612_get_vbus_voltage(void); -/* Get VBUS current in mA */ -int sy21612_get_vbus_current(void); -/* Interrupt handler */ -void sy21612_int(enum gpio_signal signal); - -#endif /* __CROS_EC_SY21612_H */ diff --git a/driver/gyro_l3gd20h.c b/driver/gyro_l3gd20h.c deleted file mode 100644 index 4fcaf15ed0..0000000000 --- a/driver/gyro_l3gd20h.c +++ /dev/null @@ -1,401 +0,0 @@ -/* 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. - */ - -/** - * L3GD20H gyro module for Chrome EC 3D digital gyroscope. - */ - -#include "accelgyro.h" -#include "common.h" -#include "console.h" -#include "driver/gyro_l3gd20h.h" -#include "hooks.h" -#include "i2c.h" -#include "task.h" -#include "util.h" - -#define CPUTS(outstr) cputs(CC_ACCEL, outstr) -#define CPRINTS(format, args...) cprints(CC_ACCEL, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_ACCEL, format, ## args) - -/* - * Struct for pairing an engineering value with the register value for a - * parameter. - */ -struct gyro_param_pair { - int val; /* Value in engineering units. */ - int reg_val; /* Corresponding register value. */ -}; - -/* - * List of angular rate range values in +/-dps's - * and their associated register values. - */ -const struct gyro_param_pair dps_ranges[] = { - {245, L3GD20_DPS_SEL_245}, - {500, L3GD20_DPS_SEL_500}, - {2000, L3GD20_DPS_SEL_2000_0}, - {2000, L3GD20_DPS_SEL_2000_1} -}; - -static inline const struct gyro_param_pair *get_range_table( - enum motionsensor_type type, int *psize) -{ - if (psize) - *psize = ARRAY_SIZE(dps_ranges); - return dps_ranges; -} - -/* List of ODR values in mHz and their associated register values. */ -const struct gyro_param_pair gyro_odr[] = { - {0, L3GD20_ODR_PD | L3GD20_LOW_ODR_MASK}, - {12500, L3GD20_ODR_12_5HZ | L3GD20_ODR_PD_MASK | L3GD20_LOW_ODR_MASK}, - {25000, L3GD20_ODR_25HZ | L3GD20_ODR_PD_MASK | L3GD20_LOW_ODR_MASK}, - {50000, L3GD20_ODR_50HZ_0 | L3GD20_ODR_PD_MASK | L3GD20_LOW_ODR_MASK}, - {50000, L3GD20_ODR_50HZ_1 | L3GD20_ODR_PD_MASK | L3GD20_LOW_ODR_MASK}, - {100000, L3GD20_ODR_100HZ | L3GD20_ODR_PD_MASK}, - {200000, L3GD20_ODR_200HZ | L3GD20_ODR_PD_MASK}, - {400000, L3GD20_ODR_400HZ | L3GD20_ODR_PD_MASK}, - {800000, L3GD20_ODR_800HZ | L3GD20_ODR_PD_MASK}, -}; - -static inline const struct gyro_param_pair *get_odr_table( - enum motionsensor_type type, int *psize) -{ - if (psize) - *psize = ARRAY_SIZE(gyro_odr); - return gyro_odr; -} - -static inline int get_ctrl_reg(enum motionsensor_type type) -{ - return L3GD20_CTRL_REG1; -} - -static inline int get_xyz_reg(enum motionsensor_type type) -{ - return L3GD20_OUT_X_L | BIT(7); -} - -/** - * @return reg value that matches the given engineering value passed in. - * The round_up flag is used to specify whether to round up or down. - * Note, this function always returns a valid reg value. If the request is - * outside the range of values, it returns the closest valid reg value. - */ -static int get_reg_val(const int eng_val, const int round_up, - const struct gyro_param_pair *pairs, const int size) -{ - int i; - for (i = 0; i < size - 1; i++) { - if (eng_val <= pairs[i].val) - break; - - if (eng_val < pairs[i+1].val) { - if (round_up) - i += 1; - break; - } - } - return pairs[i].reg_val; -} - -/** - * @return engineering value that matches the given reg val - */ -static int get_engineering_val(const int reg_val, - const struct gyro_param_pair *pairs, const int size) -{ - int i; - for (i = 0; i < size; i++) { - if (reg_val == pairs[i].reg_val) - break; - } - return pairs[i].val; -} - -/** - * Read register from Gyrometer. - */ -static inline int raw_read8(const int port, const int addr, const int reg, - int *data_ptr) -{ - return i2c_read8(port, addr, reg, data_ptr); -} - -/** - * Write register from Gyrometer. - */ -static inline int raw_write8(const int port, const int addr, const int reg, - int data) -{ - return i2c_write8(port, addr, reg, data); -} - -static int set_range(const struct motion_sensor_t *s, - int range, - int rnd) -{ - int ret, ctrl_val, range_tbl_size; - uint8_t ctrl_reg, reg_val; - const struct gyro_param_pair *ranges; - struct l3gd20_data *data = (struct l3gd20_data *)s->drv_data; - - ctrl_reg = L3GD20_CTRL_REG4; - ranges = get_range_table(s->type, &range_tbl_size); - - reg_val = get_reg_val(range, rnd, ranges, range_tbl_size); - - /* - * Lock Gyro resource to prevent another task from attempting - * to write Gyro parameters until we are done. - */ - mutex_lock(s->mutex); - - ret = raw_read8(s->port, s->addr, ctrl_reg, &ctrl_val); - if (ret != EC_SUCCESS) - goto gyro_cleanup; - - ctrl_val = (ctrl_val & ~L3GD20_RANGE_MASK) | reg_val; - ret = raw_write8(s->port, s->addr, ctrl_reg, ctrl_val); - - /* Now that we have set the range, update the driver's value. */ - if (ret == EC_SUCCESS) - data->base.range = get_engineering_val(reg_val, ranges, - range_tbl_size); - -gyro_cleanup: - mutex_unlock(s->mutex); - return EC_SUCCESS; -} - -static int get_range(const struct motion_sensor_t *s) -{ - struct l3gd20_data *data = (struct l3gd20_data *)s->drv_data; - - return data->base.range; -} - -static int get_resolution(const struct motion_sensor_t *s) -{ - return L3GD20_RESOLUTION; -} - -static int set_data_rate(const struct motion_sensor_t *s, - int rate, - int rnd) -{ - int ret, val, odr_tbl_size; - uint8_t ctrl_reg, reg_val; - const struct gyro_param_pair *data_rates; - struct l3gd20_data *data = s->drv_data; - - ctrl_reg = get_ctrl_reg(s->type); - data_rates = get_odr_table(s->type, &odr_tbl_size); - reg_val = get_reg_val(rate, rnd, data_rates, odr_tbl_size); - - /* - * Lock gyro resource to prevent another task from attempting - * to write gyro parameters until we are done. - */ - mutex_lock(s->mutex); - - ret = raw_read8(s->port, s->addr, ctrl_reg, &val); - if (ret != EC_SUCCESS) - goto gyro_cleanup; - - val = (val & ~(L3GD20_ODR_MASK | L3GD20_ODR_PD_MASK)) | - (reg_val & ~L3GD20_LOW_ODR_MASK); - ret = raw_write8(s->port, s->addr, ctrl_reg, val); - - /* Now that we have set the odr, update the driver's value. */ - if (ret == EC_SUCCESS) - data->base.odr = get_engineering_val(reg_val, data_rates, - odr_tbl_size); - - ret = raw_read8(s->port, s->addr, L3GD20_LOW_ODR, &val); - if (ret != EC_SUCCESS) - goto gyro_cleanup; - - /* We need to clear low_ODR bit for higher data rates */ - if (reg_val & L3GD20_LOW_ODR_MASK) - val |= 1; - else - val &= ~1; - - ret = raw_write8(s->port, s->addr, L3GD20_LOW_ODR, val); - if (ret != EC_SUCCESS) - goto gyro_cleanup; - - /* CTRL_REG5 24h - * [7] low-power mode = 0; - * [6] fifo disabled = 0; - * [5] Stop on fth = 0; - * [4] High pass filter enable = 1; - * [3:2] int1_sel = 0; - * [1:0] out_sel = 1; - */ - ret = raw_read8(s->port, s->addr, L3GD20_CTRL_REG5, &val); - if (ret != EC_SUCCESS) - goto gyro_cleanup; - - val |= BIT(4); /* high-pass filter enabled */ - val |= BIT(0); /* data in data reg are high-pass filtered */ - ret = raw_write8(s->port, s->addr, L3GD20_CTRL_REG5, val); - if (ret != EC_SUCCESS) - goto gyro_cleanup; - - ret = raw_read8(s->port, s->addr, L3GD20_CTRL_REG2, &val); - if (ret != EC_SUCCESS) - goto gyro_cleanup; - - /* - * Table 25. High pass filter mode configuration - * Table 26. High pass filter cut off frequency configuration - */ - val &= 0xf0; - val |= 0x04; - ret = raw_write8(s->port, s->addr, L3GD20_CTRL_REG2, val); - -gyro_cleanup: - mutex_unlock(s->mutex); - return ret; -} - -static int get_data_rate(const struct motion_sensor_t *s) -{ - struct l3gd20_data *data = (struct l3gd20_data *)s->drv_data; - - return data->base.odr; -} - -static int set_offset(const struct motion_sensor_t *s, - const int16_t *offset, - int16_t temp) -{ - /* temperature is ignored */ - struct l3gd20_data *data = s->drv_data; - data->offset[X] = offset[X]; - data->offset[Y] = offset[Y]; - data->offset[Z] = offset[Z]; - return EC_SUCCESS; -} - -static int get_offset(const struct motion_sensor_t *s, - int16_t *offset, - int16_t *temp) -{ - struct l3gd20_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; -} - -static int is_data_ready(const struct motion_sensor_t *s, int *ready) -{ - int ret, tmp; - - ret = raw_read8(s->port, s->addr, L3GD20_STATUS_REG, &tmp); - - if (ret != EC_SUCCESS) { - CPRINTS("%s type:0x%X RS Error", s->name, s->type); - return ret; - } - - *ready = (tmp & L3GD20_STS_ZYXDA_MASK) ? 1 : 0; - - return EC_SUCCESS; -} - -static int read(const struct motion_sensor_t *s, intv3_t v) -{ - uint8_t raw[6]; - uint8_t xyz_reg; - int ret, range, i, tmp = 0; - struct l3gd20_data *data = s->drv_data; - - ret = is_data_ready(s, &tmp); - if (ret != EC_SUCCESS) - return ret; - - /* - * If sensor data is not ready, return the previous read data. - * Note: return success so that motion senor task can read again - * to get the latest updated sensor data quickly. - */ - if (!tmp) { - if (v != s->raw_xyz) - memcpy(v, s->raw_xyz, sizeof(s->raw_xyz)); - return EC_SUCCESS; - } - - xyz_reg = get_xyz_reg(s->type); - - /* Read 6 bytes starting at xyz_reg */ - i2c_block_read(s->port, s->addr, xyz_reg, raw, 6); - - if (ret != EC_SUCCESS) { - CPRINTS("%s type:0x%X RD XYZ Error", s->name, s->type); - return ret; - } - - for (i = X; i <= Z; i++) - v[i] = ((int16_t)((raw[i * 2 + 1] << 8) | raw[i * 2])); - - rotate(v, *s->rot_standard_ref, v); - - /* apply offset in the device coordinates */ - range = get_range(s); - for (i = X; i <= Z; i++) - v[i] += (data->offset[i] << 5) / range; - - return EC_SUCCESS; -} - -static int init(const struct motion_sensor_t *s) -{ - int ret = 0, tmp; - - ret = raw_read8(s->port, s->addr, L3GD20_WHO_AM_I_REG, &tmp); - if (ret) - return ret; - - if (tmp != L3GD20_WHO_AM_I) - return EC_ERROR_ACCESS_DENIED; - - /* All axes are enabled */ - ret = raw_write8(s->port, s->addr, L3GD20_CTRL_REG1, 0x0f); - if (ret) - return ret; - - mutex_lock(s->mutex); - ret = raw_read8(s->port, s->addr, L3GD20_CTRL_REG4, &tmp); - if (ret) { - mutex_unlock(s->mutex); - return ret; - } - - tmp |= L3GD20_BDU_ENABLE; - ret = raw_write8(s->port, s->addr, L3GD20_CTRL_REG4, tmp); - mutex_unlock(s->mutex); - if (ret) - return ret; - - return sensor_init_done(s); -} - -const struct accelgyro_drv l3gd20h_drv = { - .init = init, - .read = read, - .set_range = set_range, - .get_range = get_range, - .get_resolution = get_resolution, - .set_data_rate = set_data_rate, - .get_data_rate = get_data_rate, - .set_offset = set_offset, - .get_offset = get_offset, -}; diff --git a/driver/gyro_l3gd20h.h b/driver/gyro_l3gd20h.h deleted file mode 100644 index 96c808b1a6..0000000000 --- a/driver/gyro_l3gd20h.h +++ /dev/null @@ -1,106 +0,0 @@ -/* 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. - */ - -/* L3GD20H gyro module for Chrome EC */ - -#ifndef __CROS_EC_GYRO_L3GD20H_H -#define __CROS_EC_GYRO_L3GD20H_H - -#include "accelgyro.h" -#include "task.h" - -/* - * 7-bit address is 110101Xb. Where 'X' is determined - * by the voltage on the ADDR pin. - */ -#define L3GD20_ADDR0_FLAGS 0x6a -#define L3GD20_ADDR1_FLAGS 0x6b - -/* who am I */ -#define L3GD20_WHO_AM_I 0xd7 - -/* Chip specific registers. */ -#define L3GD20_WHO_AM_I_REG 0x0f -#define L3GD20_CTRL_REG1 0x20 -#define L3GD20_CTRL_REG2 0x21 -#define L3GD20_CTRL_REG3 0x22 -#define L3GD20_CTRL_REG4 0x23 -#define L3GD20_CTRL_REG5 0x24 -#define L3GD20_CTRL_REFERENCE 0x25 -#define L3GD20_OUT_TEMP 0x26 -#define L3GD20_STATUS_REG 0x27 -#define L3GD20_OUT_X_L 0x28 -#define L3GD20_OUT_X_H 0x29 -#define L3GD20_OUT_Y_L 0x2a -#define L3GD20_OUT_Y_H 0x2b -#define L3GD20_OUT_Z_L 0x2c -#define L3GD20_OUT_Z_H 0x2d -#define L3GD20_FIFO_CTRL_REG 0x2e -#define L3GD20_FIFO_SRC_REG 0x2f -#define L3GD20_INT1_CFG 0x30 -#define L3GD20_INT1_SRC 0x31 -#define L3GD20_INT1_TSH_XH 0x32 -#define L3GD20_INT1_TSH_XL 0x33 -#define L3GD20_INT1_TSH_YH 0x34 -#define L3GD20_INT1_TSH_YL 0x35 -#define L3GD20_INT1_TSH_ZH 0x36 -#define L3GD20_INT1_TSH_ZL 0x37 -#define L3GD20_INT1_DURATION 0x38 -#define L3GD20_LOW_ODR 0x39 - -#define L3GD20_DPS_SEL_245 (0 << 4) -#define L3GD20_DPS_SEL_500 BIT(4) -#define L3GD20_DPS_SEL_2000_0 (2 << 4) -#define L3GD20_DPS_SEL_2000_1 (3 << 4) - -#define L3GD20_ODR_PD (0 << 3) -#define L3GD20_ODR_12_5HZ (0 << 6) -#define L3GD20_ODR_25HZ BIT(6) -#define L3GD20_ODR_50HZ_0 (2 << 6) -#define L3GD20_ODR_50HZ_1 (3 << 6) -#define L3GD20_ODR_100HZ (0 << 6) -#define L3GD20_ODR_200HZ BIT(6) -#define L3GD20_ODR_400HZ (2 << 6) -#define L3GD20_ODR_800HZ (3 << 6) - -#define L3GD20_ODR_MASK (3 << 6) -#define L3GD20_STS_ZYXDA_MASK BIT(3) -#define L3GD20_RANGE_MASK (3 << 4) -#define L3GD20_LOW_ODR_MASK BIT(0) -#define L3GD20_ODR_PD_MASK BIT(3) - -/* Min and Max sampling frequency in mHz */ -#define L3GD20_GYRO_MIN_FREQ 12500 -#define L3GD20_GYRO_MAX_FREQ 800000 - -/* - * Register : STATUS_REG - * Address : 0X27 - */ -enum l3gd20_status { - L3GD20_STS_DOWN = 0x00, - L3GD20_STS_ZYXDA_UP = 0x08, -}; - -/* - * Register : CTRL_REG4 - * Address : 0X23 - * Bit Group Name: BDU - */ -enum l3gd20_bdu { - L3GD20_BDU_DISABLE = 0x00, - L3GD20_BDU_ENABLE = 0x80, -}; - -/* Sensor resolution in number of bits. This sensor has fixed resolution. */ -#define L3GD20_RESOLUTION 16 - -extern const struct accelgyro_drv l3gd20h_drv; -struct l3gd20_data { - struct accelgyro_saved_data_t base; - int16_t offset[3]; -}; - -#endif /* __CROS_EC_GYRO_L3GD20H_H */ diff --git a/driver/ioexpander/ioexpander_nct38xx.c b/driver/ioexpander/ioexpander_nct38xx.c deleted file mode 100644 index e7fe3d9453..0000000000 --- a/driver/ioexpander/ioexpander_nct38xx.c +++ /dev/null @@ -1,470 +0,0 @@ -/* - * Copyright 2019 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. - */ - -/* GPIO expander for Nuvoton NCT38XX. */ - -#include "console.h" -#include "gpio.h" -#include "i2c.h" -#include "ioexpander.h" -#include "ioexpander_nct38xx.h" -#include "tcpci.h" - -#define CPRINTF(format, args...) cprintf(CC_GPIO, format, ## args) -#define CPRINTS(format, args...) cprints(CC_GPIO, format, ## args) - -/* - * Store the GPIO_ALERT_MASK_0/1 and chip ID registers locally. In this way, - * we don't have to read it via I2C transaction everytime. - */ -struct nct38xx_chip_data { - uint8_t int_mask[2]; - int chip_id; -}; - -static struct nct38xx_chip_data chip_data[CONFIG_IO_EXPANDER_PORT_COUNT] = { - [0 ... (CONFIG_IO_EXPANDER_PORT_COUNT - 1)] = { {0, 0}, -1 } -}; - -static int nct38xx_ioex_check_is_valid(int ioex, int port, int mask) -{ - if (chip_data[ioex].chip_id == NCT38XX_VARIANT_3808) { - if (port == 1) { - CPRINTF("Port 1 is not support in NCT3808\n"); - return EC_ERROR_INVAL; - } - if (mask & ~NCT38XXX_3808_VALID_GPIO_MASK) { - - CPRINTF("GPIO%02d is not support in NCT3808\n", - __fls(mask)); - return EC_ERROR_INVAL; - } - } - - return EC_SUCCESS; -} - -static int nct38xx_ioex_init(int ioex) -{ - int rv, val; - struct ioexpander_config_t *ioex_p = &ioex_config[ioex]; - - /* - * Check the NCT38xx part number in the register DEVICE_ID[4:2]: - * 000: NCT3807 - * 010: NCT3808 - */ - rv = i2c_read8(ioex_p->i2c_host_port, ioex_p->i2c_slave_addr, - TCPC_REG_BCD_DEV, &val); - - if (rv != EC_SUCCESS) { - CPRINTF("Failed to read NCT38XX DEV ID for IOexpander %d\n", - ioex); - return rv; - } - - chip_data[ioex].chip_id = ((uint8_t)val & NCT38XX_VARIANT_MASK) >> 2; - - /* - * NCT38XX uses the Vendor Define bit in the ALERT event to indicate - * that an IOEX IO's interrupt is triggered. - * Normally, The ALERT MASK for Vendor Define event should be set by - * the NCT38XX TCPCI driver's init function. - * However, it should be also set here if we want to test the interrupt - * function of IOEX when the NCT38XX TCPCI driver is not included. - */ - if (!IS_ENABLED(CONFIG_USB_PD_TCPM_NCT38XX)) { - rv = i2c_write16(ioex_p->i2c_host_port, - ioex_p->i2c_slave_addr, TCPC_REG_ALERT_MASK, - TCPC_REG_ALERT_VENDOR_DEF); - if (rv != EC_SUCCESS) - return rv; - } - return EC_SUCCESS; -} - -static int nct38xx_ioex_get_level(int ioex, int port, int mask, int *val) -{ - int rv, reg; - - rv = nct38xx_ioex_check_is_valid(ioex, port, mask); - if (rv != EC_SUCCESS) - return rv; - - reg = NCT38XX_REG_GPIO_DATA_IN(port); - rv = i2c_read8(ioex_config[ioex].i2c_host_port, - ioex_config[ioex].i2c_slave_addr, reg, val); - if (rv != EC_SUCCESS) - return rv; - - *val = !!(*val & mask); - - return EC_SUCCESS; -} - -static int nct38xx_ioex_set_level(int ioex, int port, int mask, int value) -{ - int rv, reg, val; - - rv = nct38xx_ioex_check_is_valid(ioex, port, mask); - if (rv != EC_SUCCESS) - return rv; - - reg = NCT38XX_REG_GPIO_DATA_OUT(port); - - rv = i2c_read8(ioex_config[ioex].i2c_host_port, - ioex_config[ioex].i2c_slave_addr, reg, &val); - if (rv != EC_SUCCESS) - return rv; - - if (value) - val |= mask; - else - val &= ~mask; - - return i2c_write8(ioex_config[ioex].i2c_host_port, - ioex_config[ioex].i2c_slave_addr, reg, val); -} - -static int nct38xx_ioex_get_flags(int ioex, int port, int mask, int *flags) -{ - int rv, reg, val, i2c_port, i2c_addr; - struct ioexpander_config_t *ioex_p = &ioex_config[ioex]; - - i2c_port = ioex_p->i2c_host_port; - i2c_addr = ioex_p->i2c_slave_addr; - - rv = nct38xx_ioex_check_is_valid(ioex, port, mask); - if (rv != EC_SUCCESS) - return rv; - - reg = NCT38XX_REG_GPIO_DIR(port); - rv = i2c_read8(i2c_port, i2c_addr, reg, &val); - if (rv != EC_SUCCESS) - return rv; - - if (val & mask) - *flags |= GPIO_OUTPUT; - else - *flags |= GPIO_INPUT; - - reg = NCT38XX_REG_GPIO_DATA_IN(port); - rv = i2c_read8(i2c_port, i2c_addr, reg, &val); - if (rv != EC_SUCCESS) - return rv; - - if (val & mask) - *flags |= GPIO_HIGH; - else - *flags |= GPIO_LOW; - - reg = NCT38XX_REG_GPIO_OD_SEL(port); - rv = i2c_read8(i2c_port, i2c_addr, reg, &val); - if (rv != EC_SUCCESS) - return rv; - - if (val & mask) - *flags |= GPIO_OPEN_DRAIN; - - return EC_SUCCESS; -} - -static int nct38xx_ioex_sel_int_type(int i2c_port, int i2c_addr, int port, - int mask, int flags) -{ - int rv; - int reg_rising, reg_falling; - int rising, falling; - - reg_rising = NCT38XX_REG_GPIO_ALERT_RISE(port); - rv = i2c_read8(i2c_port, i2c_addr, reg_rising, &rising); - if (rv != EC_SUCCESS) - return rv; - - reg_falling = NCT38XX_REG_GPIO_ALERT_FALL(port); - rv = i2c_read8(i2c_port, i2c_addr, reg_falling, &falling); - if (rv != EC_SUCCESS) - return rv; - - /* Handle interrupt for level trigger */ - if ((flags & GPIO_INT_F_HIGH) || (flags & GPIO_INT_F_LOW)) { - int reg_level, level; - - reg_level = NCT38XX_REG_GPIO_ALERT_LEVEL(port); - rv = i2c_read8(i2c_port, i2c_addr, reg_level, &level); - if (rv != EC_SUCCESS) - return rv; - /* - * For "level" triggered interrupt, the related bit in - * ALERT_RISE and ALERT_FALL registers must be 0 - */ - rising &= ~mask; - falling &= ~mask; - if (flags & GPIO_INT_F_HIGH) - level |= mask; - else - level &= ~mask; - - rv = i2c_write8(i2c_port, i2c_addr, reg_rising, rising); - if (rv != EC_SUCCESS) - return rv; - rv = i2c_write8(i2c_port, i2c_addr, reg_falling, falling); - if (rv != EC_SUCCESS) - return rv; - rv = i2c_write8(i2c_port, i2c_addr, reg_level, level); - if (rv != EC_SUCCESS) - return rv; - } else if ((flags & GPIO_INT_F_RISING) || - (flags & GPIO_INT_F_FALLING)) { - if (flags & GPIO_INT_F_RISING) - rising |= mask; - else - rising &= ~mask; - if (flags & GPIO_INT_F_FALLING) - falling |= mask; - else - falling &= ~mask; - rv = i2c_write8(i2c_port, i2c_addr, reg_rising, rising); - if (rv != EC_SUCCESS) - return rv; - rv = i2c_write8(i2c_port, i2c_addr, reg_falling, falling); - if (rv != EC_SUCCESS) - return rv; - } - return EC_SUCCESS; -} - -static int nct38xx_ioex_set_flags_by_mask(int ioex, int port, int mask, - int flags) -{ - int rv, reg, val, i2c_port, i2c_addr; - struct ioexpander_config_t *ioex_p = &ioex_config[ioex]; - - i2c_port = ioex_p->i2c_host_port; - i2c_addr = ioex_p->i2c_slave_addr; - - rv = nct38xx_ioex_check_is_valid(ioex, port, mask); - if (rv != EC_SUCCESS) - return rv; - - /* - * GPIO port 0 muxs with alternative function. Disable the alternative - * function before setting flags. - */ - if (port == 0) { - /* GPIO03 in NCT3807 is not muxed with other function. */ - if (!(chip_data[ioex].chip_id == - NCT38XX_VARIANT_3807 && mask & 0x08)) { - reg = NCT38XX_REG_MUX_CONTROL; - rv = i2c_read8(i2c_port, i2c_addr, reg, &val); - if (rv != EC_SUCCESS) - return rv; - - val = (val | mask); - rv = i2c_write8(i2c_port, i2c_addr, reg, val); - if (rv != EC_SUCCESS) - return rv; - } - } - - val = flags & ~NCT38XX_SUPPORT_GPIO_FLAGS; - if (val) { - CPRINTF("Flag 0x%08x is not supported\n", val); - return EC_ERROR_INVAL; - } - - /* Select open drain 0:push-pull 1:open-drain */ - reg = NCT38XX_REG_GPIO_OD_SEL(port); - rv = i2c_read8(i2c_port, i2c_addr, reg, &val); - if (rv != EC_SUCCESS) - return rv; - - if (flags & GPIO_OPEN_DRAIN) - val |= mask; - else - val &= ~mask; - rv = i2c_write8(i2c_port, i2c_addr, reg, val); - if (rv != EC_SUCCESS) - return rv; - - nct38xx_ioex_sel_int_type(i2c_port, i2c_addr, port, mask, flags); - - /* Configure the output level */ - reg = NCT38XX_REG_GPIO_DATA_OUT(port); - rv = i2c_read8(i2c_port, i2c_addr, reg, &val); - if (rv != EC_SUCCESS) - return rv; - - if (flags & GPIO_HIGH) - val |= mask; - else if (flags & GPIO_LOW) - val &= ~mask; - rv = i2c_write8(i2c_port, i2c_addr, reg, val); - if (rv != EC_SUCCESS) - return rv; - - reg = NCT38XX_REG_GPIO_DIR(port); - rv = i2c_read8(i2c_port, i2c_addr, reg, &val); - if (rv != EC_SUCCESS) - return rv; - - if (flags & GPIO_OUTPUT) - val |= mask; - else - val &= ~mask; - - return i2c_write8(i2c_port, i2c_addr, reg, val); -} - -/* - * The following functions are used for IO's interrupt support. - * - * please note that if the system needs to use an IO on NCT38XX to support - * the interrupt, the following two consideration should be taken into account. - * 1. Interrupt latency: - * Because it requires to access the registers of NCT38XX via I2C - * transaction to know the interrupt event, there is some added latency - * for the interrupt handling. If the interrupt requires short latency, - * we do not recommend to connect such a signal to the NCT38XX. - * - * 2. Shared ALERT pin: - * Because the ALERT pin is shared also with the TCPC ALERT, we do not - * recommend to connect any signal that may generate a high rate of - * interrupts so it will not interfere with the normal work of the - * TCPC. - */ -static int nct38xx_ioex_enable_interrupt(int ioex, int port, int mask, - int enable) -{ - int rv, reg, val; - struct ioexpander_config_t *ioex_p = &ioex_config[ioex]; - - rv = nct38xx_ioex_check_is_valid(ioex, port, mask); - if (rv != EC_SUCCESS) - return rv; - - /* Clear the pending bit */ - reg = NCT38XX_REG_GPIO_ALERT_STAT(port); - rv = i2c_read8(ioex_p->i2c_host_port, ioex_p->i2c_slave_addr, - reg, &val); - if (rv != EC_SUCCESS) - return rv; - - val |= mask; - rv = i2c_write8(ioex_p->i2c_host_port, ioex_p->i2c_slave_addr, - reg, val); - if (rv != EC_SUCCESS) - return rv; - - reg = NCT38XX_REG_GPIO_ALERT_MASK(port); - if (enable) { - /* Enable the alert mask */ - chip_data[ioex].int_mask[port] |= mask; - val = chip_data[ioex].int_mask[port]; - } else { - /* Disable the alert mask */ - chip_data[ioex].int_mask[port] &= ~mask; - val = chip_data[ioex].int_mask[port]; - } - - return i2c_write8(ioex_p->i2c_host_port, ioex_p->i2c_slave_addr, - reg, val); -} - -int nct38xx_ioex_event_handler(int ioex) -{ - int reg, int_status, int_mask; - int i, j, total_port; - const struct ioex_info *g; - struct ioexpander_config_t *ioex_p = &ioex_config[ioex]; - int rv = 0; - - int_mask = chip_data[ioex].int_mask[0] | ( - chip_data[ioex].int_mask[1] << 8); - reg = NCT38XX_REG_GPIO_ALERT_STAT(0); - /* - * Read ALERT_STAT_0 and ALERT_STAT_1 register in a single I2C - * transaction to increase efficiency - */ - rv = i2c_read16(ioex_p->i2c_host_port, ioex_p->i2c_slave_addr, - reg, &int_status); - if (rv != EC_SUCCESS) - return rv; - - int_status = int_status & int_mask; - /* - * Clear the changed status bits in ALERT_STAT_0 and ALERT_STAT_1 - * register in a single I2C transaction to increase efficiency - */ - rv = i2c_write16(ioex_p->i2c_host_port, ioex_p->i2c_slave_addr, - reg, int_status); - if (rv != EC_SUCCESS) - return rv; - - /* For NCT3808, only check one port */ - total_port = (chip_data[ioex].chip_id == NCT38XX_VARIANT_3808) ? - NCT38XX_NCT3808_MAX_IO_PORT : - NCT38XX_NCT3807_MAX_IO_PORT; - for (i = 0; i < total_port; i++) { - uint8_t pending; - - pending = int_status >> (i * 8); - - if (!pending) - continue; - - for (j = 0, g = ioex_list; j < ioex_ih_count; j++, g++) { - - if (ioex == g->ioex && i == g->port && - (pending & g->mask)) { - ioex_irq_handlers[j](j); - pending &= ~g->mask; - if (!pending) - break; - } - - } - } - - return EC_SUCCESS; -} - -/* - * Normally, the ALERT MASK for Vendor Define event should be checked by - * the NCT38XX TCPCI driver's tcpc_alert function. - * However, it should be checked here if we want to test the interrupt - * function of IOEX when the NCT38XX TCPCI driver is not included. - */ -void nct38xx_ioex_handle_alert(int ioex) -{ - int rv, status; - struct ioexpander_config_t *ioex_p = &ioex_config[ioex]; - - rv = i2c_read16(ioex_p->i2c_host_port, ioex_p->i2c_slave_addr, - TCPC_REG_ALERT, &status); - if (rv != EC_SUCCESS) - CPRINTF("fail to read ALERT register\n"); - - if (status & TCPC_REG_ALERT_VENDOR_DEF) { - rv = i2c_write16(ioex_p->i2c_host_port, - ioex_p->i2c_slave_addr, TCPC_REG_ALERT, - TCPC_REG_ALERT_VENDOR_DEF); - if (rv != EC_SUCCESS) { - CPRINTF("Fail to clear Vendor Define mask\n"); - return; - } - nct38xx_ioex_event_handler(ioex); - } -} - -const struct ioexpander_drv nct38xx_ioexpander_drv = { - .init = &nct38xx_ioex_init, - .get_level = &nct38xx_ioex_get_level, - .set_level = &nct38xx_ioex_set_level, - .get_flags_by_mask = &nct38xx_ioex_get_flags, - .set_flags_by_mask = &nct38xx_ioex_set_flags_by_mask, - .enable_interrupt = &nct38xx_ioex_enable_interrupt, -}; diff --git a/driver/ioexpander/ioexpander_nct38xx.h b/driver/ioexpander/ioexpander_nct38xx.h deleted file mode 100644 index 56dfe76e04..0000000000 --- a/driver/ioexpander/ioexpander_nct38xx.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2019 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. - */ - -#ifndef __CROS_EC_IOEXPANDER_NCT38XX_H -#define __CROS_EC_IOEXPANDER_NCT38XX_H -/* - * NCT38XX registers are defined in the driver/tcpm/nct38xx.h. - * No matter they are used by TCPC or IO Expander driver. - */ -#include "nct38xx.h" - -/* - * The interrupt handler to handle Vendor Define ALERT event from IOEX chip. - * - * Normally, the Vendor Define event should be checked by the NCT38XX TCPCI - * driver's tcpc_alert function. - * This function is only included when NCT38XX TCPC driver is not included. - * (i.e. CONFIG_USB_PD_TCPM_NCT38XX is not defined) - */ -void nct38xx_ioex_handle_alert(int ioex); - -/* - * Check which IO's interrupt event is triggered. If any, call its - * registered interrupt handler. - */ -int nct38xx_ioex_event_handler(int ioex); - -extern const struct ioexpander_drv nct38xx_ioexpander_drv; - -#endif /* defined(__CROS_EC_IOEXPANDER_NCT38XX_H) */ diff --git a/driver/ioexpander/it8300.h b/driver/ioexpander/it8300.h deleted file mode 100644 index 2b47e7f3e1..0000000000 --- a/driver/ioexpander/it8300.h +++ /dev/null @@ -1,106 +0,0 @@ -/* Copyright 2018 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. - * - * ITE IT8300 I/O Port expander driver header - */ - -#ifndef __CROS_EC_IOEXPANDER_IT8300_H -#define __CROS_EC_IOEXPANDER_IT8300_H - -#include "i2c.h" - -/* Gather Interrupt Status Register */ -#define IT8300_GISR 0x0 - -/* Interrupt Status Registers */ -#define IT8300_ISR_A 0x6 -#define IT8300_ISR_B 0x7 -#define IT8300_ISR_C 0x28 -#define IT8300_ISR_D 0x2E -#define IT8300_ISR_E 0x2F - -/* Port Data Register Groups */ -#define IT8300_PDGR_A 0x1 -#define IT8300_PDGR_B 0x2 -#define IT8300_PDGR_C 0x3 -#define IT8300_PDGR_D 0x4 -#define IT8300_PDGR_E 0x5 - -/* GPIO Port Control n Registers */ -#define IT8300_GPCR_A0 0x10 -#define IT8300_GPCR_A1 0x11 -#define IT8300_GPCR_A2 0x12 -#define IT8300_GPCR_A3 0x13 -#define IT8300_GPCR_A4 0x14 -#define IT8300_GPCR_A5 0x15 -#define IT8300_GPCR_A6 0x16 -#define IT8300_GPCR_A7 0x17 - -#define IT8300_GPCR_B0 0x18 -#define IT8300_GPCR_B1 0x19 -#define IT8300_GPCR_B2 0x1A -#define IT8300_GPCR_B3 0x1B -#define IT8300_GPCR_B4 0x1C -#define IT8300_GPCR_B5 0x1D -#define IT8300_GPCR_B6 0x1E - -#define IT8300_GPCR_C0 0x20 -#define IT8300_GPCR_C1 0x21 -#define IT8300_GPCR_C2 0x22 -#define IT8300_GPCR_C3 0x23 -#define IT8300_GPCR_C4 0x24 -#define IT8300_GPCR_C5 0x25 -#define IT8300_GPCR_C6 0x26 - -#define IT8300_GPCR_D0 0x08 -#define IT8300_GPCR_D1 0x09 -#define IT8300_GPCR_D2 0x0A -#define IT8300_GPCR_D3 0x0B -#define IT8300_GPCR_D4 0x0C -#define IT8300_GPCR_D5 0x0D - -#define IT8300_GPCR_E0 0x32 - -#define IT8300_GPCR_E2 0x34 -#define IT8300_GPCR_E3 0x35 -#define IT8300_GPCR_E4 0x36 -#define IT8300_GPCR_E5 0x37 -#define IT8300_GPCR_E6 0x38 - -#define IT8300_GPCR_GPI_MODE BIT(7) -#define IT8300_GPCR_GP0_MODE BIT(6) -#define IT8300_GPCR_PULL_UP_EN BIT(2) -#define IT8300_GPCR_PULL_DN_EN BIT(1) - -/* EXGPIO Clear Alert */ -#define IT8300_ECA 0x30 - -/* EXGPIO Alert Enable */ -#define IT8300_EAE 0x31 - -/* Port Data Mirror Registers */ -#define IT8300_PDMRA_A 0x29 -#define IT8300_PDMRA_B 0x2A -#define IT8300_PDMRA_C 0x2B -#define IT8300_PDMRA_D 0x2C -#define IT8300_PDMRA_E 0x2D - -/* Output Open-Drain Enable Registers */ -#define IT8300_OODER_A 0x39 -#define IT8300_OODER_B 0x3A -#define IT8300_OODER_C 0x3B -#define IT8300_OODER_D 0x3C -#define IT8300_OODER_E 0x3D - -/* IT83200 Port GPIOs */ -#define IT8300_GPX_0 BIT(0) -#define IT8300_GPX_1 BIT(1) -#define IT8300_GPX_2 BIT(2) -#define IT8300_GPX_3 BIT(3) -#define IT8300_GPX_4 BIT(4) -#define IT8300_GPX_5 BIT(5) -#define IT8300_GPX_6 BIT(6) -#define IT8300_GPX_7 BIT(7) - -#endif /* __CROS_EC_IOEXPANDER_IT8300_H */ diff --git a/driver/ioexpander/it8801.c b/driver/ioexpander/it8801.c deleted file mode 100644 index 6b1184c740..0000000000 --- a/driver/ioexpander/it8801.c +++ /dev/null @@ -1,227 +0,0 @@ -/* Copyright 2019 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. - */ - -#include "common.h" -#include "console.h" -#include "gpio.h" -#include "hooks.h" -#include "i2c.h" -#include "it8801.h" -#include "keyboard_raw.h" -#include "keyboard_scan.h" -#include "registers.h" -#include "task.h" - -#define CPRINTS(format, args...) cprints(CC_KEYSCAN, format, ## args) - -static int it8801_read(int reg, int *data) -{ - return i2c_read8(I2C_PORT_IO_EXPANDER_IT8801, IT8801_I2C_ADDR, - reg, data); -} - -static int it8801_write(int reg, int data) -{ - return i2c_write8(I2C_PORT_IO_EXPANDER_IT8801, IT8801_I2C_ADDR, - reg, data); -} - -struct it8801_vendor_id_t { - uint8_t chip_id; - uint8_t reg; -}; - -static const struct it8801_vendor_id_t it8801_vendor_id_verify[] = { - { 0x12, IT8801_REG_HBVIDR}, - { 0x83, IT8801_REG_LBVIDR}, -}; - -static int it8801_check_vendor_id(void) -{ - int i, ret, val; - - /* Verify vendor ID registers(16-bits). */ - for (i = 0; i < ARRAY_SIZE(it8801_vendor_id_verify); i++) { - ret = it8801_read(it8801_vendor_id_verify[i].reg, &val); - - if (ret != EC_SUCCESS) - return ret; - - if (val != it8801_vendor_id_verify[i].chip_id) - return EC_ERROR_UNKNOWN; - } - - return EC_SUCCESS; -} - -void keyboard_raw_init(void) -{ - int ret, val; - - /* Verify Vendor ID registers. */ - ret = it8801_check_vendor_id(); - if (ret) { - CPRINTS("Failed to read IT8801 vendor id %x", ret); - return; - } - - /* KSO alternate function switching(KSO[21:20, 18]). */ - it8801_write(IT8801_REG_GPIO01_KSO18, IT8801_REG_MASK_GPIOAFS_FUNC2); - it8801_write(IT8801_REG_GPIO22_KSO21, IT8801_REG_MASK_GPIOAFS_FUNC2); - it8801_write(IT8801_REG_GPIO23_KSO20, IT8801_REG_MASK_GPIOAFS_FUNC2); - - /* Start with KEYBOARD_COLUMN_ALL, KSO[22:11, 6:0] output low. */ - it8801_write(IT8801_REG_KSOMCR, IT8801_REG_MASK_AKSOSC); - - if (IS_ENABLED(CONFIG_KEYBOARD_COL2_INVERTED)) { - /* - * Since most of the KSO pins can't drive up, we'll must use - * a pin capable of being a GPIO instead and use the GPIO - * feature to do the required inverted push pull. - */ - it8801_write(IT8801_REG_GPIO23_KSO20, IT8801_REG_MASK_GPIODIR); - - /* Start with KEYBOARD_COLUMN_ALL, output high(so selected). */ - it8801_read(IT8801_REG_GPIOG2SOVR, &val); - it8801_write(IT8801_REG_GPIOG2SOVR, val | IT8801_REG_GPIO23SOV); - } - - /* Keyboard scan in interrupt enable register */ - it8801_write(IT8801_REG_KSIIER, 0xff); - /* Gather KSI interrupt enable */ - it8801_write(IT8801_REG_GIECR, IT8801_REG_MASK_GKSIIE); - /* Alert response enable */ - it8801_write(IT8801_REG_SMBCR, IT8801_REG_MASK_ARE); - - keyboard_raw_enable_interrupt(0); -} - -void keyboard_raw_task_start(void) -{ - keyboard_raw_enable_interrupt(1); -} - -static const uint8_t kso_mapping[] = { - 0, 1, 20, 3, 4, 5, 6, 17, 18, 16, 15, 11, 12, -#ifdef CONFIG_KEYBOARD_KEYPAD - 13, 14 -#endif -}; -BUILD_ASSERT(ARRAY_SIZE(kso_mapping) == KEYBOARD_COLS_MAX); - -test_mockable void keyboard_raw_drive_column(int col) -{ - int kso_val, val; - - /* Tri-state all outputs */ - if (col == KEYBOARD_COLUMN_NONE) { - /* KSO[22:11, 6:0] output high */ - kso_val = IT8801_REG_MASK_KSOSDIC | IT8801_REG_MASK_AKSOSC; - - if (IS_ENABLED(CONFIG_KEYBOARD_COL2_INVERTED)) { - /* Output low(so not selected). */ - it8801_read(IT8801_REG_GPIOG2SOVR, &val); - it8801_write(IT8801_REG_GPIOG2SOVR, val & - ~IT8801_REG_GPIO23SOV); - } - } - /* Assert all outputs */ - else if (col == KEYBOARD_COLUMN_ALL) { - /* KSO[22:11, 6:0] output low */ - kso_val = IT8801_REG_MASK_AKSOSC; - - if (IS_ENABLED(CONFIG_KEYBOARD_COL2_INVERTED)) { - /* Output high(so selected). */ - it8801_read(IT8801_REG_GPIOG2SOVR, &val); - it8801_write(IT8801_REG_GPIOG2SOVR, val | - IT8801_REG_GPIO23SOV); - } - } else { - /* To check if column is valid or not. */ - if (col >= KEYBOARD_COLS_MAX) - return; - /* - * Selected KSO[20, 18:11, 6:3, 1:0] output low, - * all others KSO output high. - */ - kso_val = kso_mapping[col]; - - if (IS_ENABLED(CONFIG_KEYBOARD_COL2_INVERTED)) { - /* GPIO23 is inverted. */ - if (col == IT8801_REG_MASK_SELKSO2) { - /* Output high(so selected). */ - it8801_read(IT8801_REG_GPIOG2SOVR, &val); - it8801_write(IT8801_REG_GPIOG2SOVR, val | - IT8801_REG_GPIO23SOV); - } else { - /* Output low(so not selected). */ - it8801_read(IT8801_REG_GPIOG2SOVR, &val); - it8801_write(IT8801_REG_GPIOG2SOVR, val & - ~IT8801_REG_GPIO23SOV); - } - } - } - - it8801_write(IT8801_REG_KSOMCR, kso_val); -} - -test_mockable int keyboard_raw_read_rows(void) -{ - int data = 0; - int ksieer = 0; - - it8801_read(IT8801_REG_KSIDR, &data); - - /* This register needs to write clear after reading data */ - it8801_read(IT8801_REG_KSIEER, &ksieer); - it8801_write(IT8801_REG_KSIEER, ksieer); - - /* Bits are active-low, so invert returned levels */ - return (~data) & 0xff; -} - -void keyboard_raw_enable_interrupt(int enable) -{ - if (enable) { - it8801_write(IT8801_REG_KSIEER, 0xff); - gpio_clear_pending_interrupt(GPIO_IT8801_SMB_INT); - gpio_enable_interrupt(GPIO_IT8801_SMB_INT); - } else { - gpio_disable_interrupt(GPIO_IT8801_SMB_INT); - } -} - -void io_expander_it8801_interrupt(enum gpio_signal signal) -{ - /* Wake the scan task */ - task_wake(TASK_ID_KEYSCAN); -} - -static void dump_register(int reg) -{ - int rv; - int data; - - ccprintf("[%Xh] = ", reg); - - rv = it8801_read(reg, &data); - - if (!rv) - ccprintf("0x%02x\n", data); - else - ccprintf("ERR (%d)\n", rv); -} - -static int it8801_dump(int argc, char **argv) -{ - dump_register(IT8801_REG_KSIIER); - dump_register(IT8801_REG_KSIEER); - dump_register(IT8801_REG_KSIDR); - dump_register(IT8801_REG_KSOMCR); - - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(it8801_dump, it8801_dump, "NULL", - "Dumps IT8801 registers"); diff --git a/driver/ioexpander/it8801.h b/driver/ioexpander/it8801.h deleted file mode 100644 index 9b84adf764..0000000000 --- a/driver/ioexpander/it8801.h +++ /dev/null @@ -1,46 +0,0 @@ -/* Copyright 2019 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. - * - * IT8801 is an I/O expander with the keyboard matrix controller. - * - */ - -#ifndef __CROS_EC_IO_EXPANDER_IT8801_H -#define __CROS_EC_IO_EXPANDER_IT8801_H - -/* I2C slave address(7-bit without R/W) */ -#define IT8801_I2C_ADDR 0x38 - -/* Keyboard Matrix Scan control (KBS) */ -#define IT8801_REG_KSOMCR 0x40 -#define IT8801_REG_MASK_KSOSDIC BIT(7) -#define IT8801_REG_MASK_KSE BIT(6) -#define IT8801_REG_MASK_AKSOSC BIT(5) -#define IT8801_REG_KSIDR 0x41 -#define IT8801_REG_KSIEER 0x42 -#define IT8801_REG_KSIIER 0x43 -#define IT8801_REG_SMBCR 0xfa -#define IT8801_REG_MASK_ARE BIT(4) -#define IT8801_REG_GIECR 0xfb -#define IT8801_REG_MASK_GKSIIE BIT(3) -#define IT8801_REG_GPIO10 0x12 -#define IT8801_REG_GPIO00_KSO19 0x0a -#define IT8801_REG_GPIO01_KSO18 0x0b -#define IT8801_REG_GPIO22_KSO21 0x1c -#define IT8801_REG_GPIO23_KSO20 0x1d -#define IT8801_REG_MASK_GPIOAFS_PULLUP BIT(7) -#define IT8801_REG_MASK_GPIOAFS_FUNC2 BIT(6) -#define IT8801_REG_MASK_GPIODIR BIT(5) -#define IT8801_REG_MASK_GPIOPUE BIT(0) -#define IT8801_REG_GPIOG2SOVR 0x07 -#define IT8801_REG_GPIO23SOV BIT(3) -#define IT8801_REG_MASK_SELKSO2 0x02 -#define IT8801_REG_LBVIDR 0xFE -#define IT8801_REG_HBVIDR 0xFF -#define IT8801_KSO_COUNT 18 - -/* ISR for IT8801's SMB_INT# */ -void io_expander_it8801_interrupt(enum gpio_signal signal); - -#endif /* __CROS_EC_KBEXPANDER_IT8801_H */ diff --git a/driver/ioexpander/pca9534.c b/driver/ioexpander/pca9534.c deleted file mode 100644 index d56eb864cb..0000000000 --- a/driver/ioexpander/pca9534.c +++ /dev/null @@ -1,52 +0,0 @@ -/* Copyright 2014 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. - * - * NXP PCA9534 I/O expander - */ - -#include "i2c.h" -#include "pca9534.h" - -static int pca9534_pin_read(const int port, const uint16_t addr_flags, - int reg, int pin, int *val) -{ - int ret; - ret = i2c_read8(port, addr_flags, reg, val); - *val = (*val & BIT(pin)) ? 1 : 0; - return ret; -} - -static int pca9534_pin_write(const int port, const uint16_t addr_flags, - int reg, int pin, int val) -{ - int ret, v; - ret = i2c_read8(port, addr_flags, reg, &v); - if (ret != EC_SUCCESS) - return ret; - v &= ~BIT(pin); - if (val) - v |= 1 << pin; - return i2c_write8(port, addr_flags, reg, v); -} - -int pca9534_get_level(const int port, const uint16_t addr_flags, - int pin, int *level) -{ - return pca9534_pin_read(port, addr_flags, - PCA9534_REG_INPUT, pin, level); -} - -int pca9534_set_level(const int port, const uint16_t addr_flags, - int pin, int level) -{ - return pca9534_pin_write(port, addr_flags, - PCA9534_REG_OUTPUT, pin, level); -} - -int pca9534_config_pin(const int port, const uint16_t addr_flags, - int pin, int is_input) -{ - return pca9534_pin_write(port, addr_flags, - PCA9534_REG_CONFIG, pin, is_input); -} diff --git a/driver/ioexpander/pca9534.h b/driver/ioexpander/pca9534.h deleted file mode 100644 index 0fec577576..0000000000 --- a/driver/ioexpander/pca9534.h +++ /dev/null @@ -1,59 +0,0 @@ -/* Copyright 2014 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. - * - * NXP PCA9534 I/O expander - */ - -#ifndef __CROS_EC_IOEXPANDER_PCA9534_H -#define __CROS_EC_IOEXPANDER_PCA9534_H - -#define PCA9534_REG_INPUT 0x0 -#define PCA9534_REG_OUTPUT 0x1 -#define PCA9534_REG_CONFIG 0x3 - -#define PCA9534_OUTPUT 0 -#define PCA9534_INPUT 1 - -/* - * Get input level. Note that this reflects the actual level on the - * pin, even if the pin is configured as output. - * - * @param port The I2C port of PCA9534. - * @param addr The address of PCA9534. - * @param pin The index of the pin to read. - * @param level The pointer to where the read level is stored. - * - * @return EC_SUCCESS, or EC_ERROR_* on error. - */ -int pca9534_get_level(const int port, const uint16_t addr_flags, - int pin, int *level); - -/* - * Set output level. This function has no effect if the pin is - * configured as input. - * - * @param port The I2C port of PCA9534. - * @param addr The address of PCA9534. - * @param pin The index of the pin to set. - * @param level The level to set. - * - * @return EC_SUCCESS, or EC_ERROR_* on error. - */ -int pca9534_set_level(const int port, const uint16_t addr_flags, - int pin, int level); - -/* - * Config a pin as input or output. - * - * @param port The I2C port of PCA9534. - * @param addr The address of PCA9534. - * @param pin The index of the pin to set. - * @param is_input PCA9534_INPUT or PCA9534_OUTPUT. - * - * @return EC_SUCCESS, or EC_ERROR_* on error. - */ -int pca9534_config_pin(const int port, const uint16_t addr_flags, - int pin, int is_input); - -#endif /* __CROS_EC_IOEXPANDER_PCA9534_H */ diff --git a/driver/ioexpander/pca9555.h b/driver/ioexpander/pca9555.h deleted file mode 100644 index 273f898821..0000000000 --- a/driver/ioexpander/pca9555.h +++ /dev/null @@ -1,45 +0,0 @@ -/* Copyright 2017 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. - * - * NXP PCA9555 I/O Port expander driver header - */ - -#ifndef __CROS_EC_IOEXPANDER_PCA9555_H -#define __CROS_EC_IOEXPANDER_PCA9555_H - -#include "i2c.h" - -#define PCA9555_CMD_INPUT_PORT_0 0 -#define PCA9555_CMD_INPUT_PORT_1 1 -#define PCA9555_CMD_OUTPUT_PORT_0 2 -#define PCA9555_CMD_OUTPUT_PORT_1 3 -#define PCA9555_CMD_POLARITY_INVERSION_PORT_0 4 -#define PCA9555_CMD_POLARITY_INVERSION_PORT_1 5 -#define PCA9555_CMD_CONFIGURATION_PORT_0 6 -#define PCA9555_CMD_CONFIGURATION_PORT_1 7 - -#define PCA9555_IO_0 BIT(0) -#define PCA9555_IO_1 BIT(1) -#define PCA9555_IO_2 BIT(2) -#define PCA9555_IO_3 BIT(3) -#define PCA9555_IO_4 BIT(4) -#define PCA9555_IO_5 BIT(5) -#define PCA9555_IO_6 BIT(6) -#define PCA9555_IO_7 BIT(7) - -static inline int pca9555_read(const int port, - const uint16_t i2c_addr_flags, - int reg, int *data_ptr) -{ - return i2c_read8(port, i2c_addr_flags, reg, data_ptr); -} - -static inline int pca9555_write(const int port, - const uint16_t i2c_addr_flags, - int reg, int data) -{ - return i2c_write8(port, i2c_addr_flags, reg, data); -} - -#endif /* __CROS_EC_IOEXPANDER_PCA9555_H */ diff --git a/driver/led/ds2413.c b/driver/led/ds2413.c deleted file mode 100644 index b856d85671..0000000000 --- a/driver/led/ds2413.c +++ /dev/null @@ -1,166 +0,0 @@ -/* Copyright 2013 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. - */ - -/* Power LED control for Chrome EC */ - -#include "charge_state.h" -#include "console.h" -#include "hooks.h" -#include "onewire.h" -#include "timer.h" -#include "util.h" - -#define ONEWIRE_RETRIES 10 - -enum led_color { - LED_OFF = 0, - LED_RED, - LED_YELLOW, - LED_GREEN, - LED_COLOR_COUNT /* Number of colors, not a color itself */ -}; - -static const uint8_t led_masks[LED_COLOR_COUNT] = {0xff, 0xfe, 0xfc, 0xfd}; -static const char * const color_names[LED_COLOR_COUNT] = { - "off", "red", "yellow", "green"}; - -/** - * Set the onewire LED GPIO controller outputs - * - * @param mask Mask of outputs to enable - * - * @return EC_SUCCESS, or non-zero if error. - */ -static int led_set_mask(int mask) -{ - int rv; - - /* Reset the 1-wire bus */ - rv = onewire_reset(); - if (rv) - return rv; - - /* Skip ROM, since only one device */ - onewire_write(0xcc); - - /* Write and turn on the LEDs */ - onewire_write(0x5a); - onewire_write(mask); - onewire_write(~mask); /* Repeat inverted */ - - rv = onewire_read(); /* Confirmation byte */ - if (rv != 0xaa) - return EC_ERROR_UNKNOWN; - - /* The next byte is a read-back of the chip status. Since we're only - * using lines as outputs, we can ignore it. */ - return EC_SUCCESS; -} - -static int led_set(enum led_color color) -{ - int rv = EC_SUCCESS; - int i; - - /* - * 1-wire communication can fail for timing reasons in the current - * system. We have a limited timing window to send/receive bits, but - * we can't disable interrupts for the rest of the system to guarantee - * we hit that window. Instead, simply retry the low-level command a - * few times. - */ - for (i = 0; i < ONEWIRE_RETRIES; i++) { - rv = led_set_mask(led_masks[color]); - if (rv == EC_SUCCESS) - break; - - /* - * Sleep for a bit between tries. This gives the 1-wire GPIO - * chip time to recover from the failed attempt, and allows - * lower-priority tasks a chance to run. - */ - usleep(100); - } - - return rv; -} - -/*****************************************************************************/ -/* Hooks */ - -static void onewire_led_tick(void) -{ - static enum led_color current_color = LED_COLOR_COUNT; - static int tick_count; - - enum led_color new_color = LED_OFF; - uint32_t chflags = charge_get_flags(); - - tick_count++; - - if (!(chflags & CHARGE_FLAG_EXTERNAL_POWER)) { - /* AC isn't present, so the power LED on the AC plug is off */ - current_color = LED_OFF; - return; - } - - /* Translate charge state to LED color */ - switch (charge_get_state()) { - case PWR_STATE_IDLE: - if (chflags & CHARGE_FLAG_FORCE_IDLE) - new_color = (tick_count & 1) ? LED_GREEN : LED_OFF; - else - new_color = LED_GREEN; - break; - case PWR_STATE_CHARGE: - new_color = LED_YELLOW; - break; - case PWR_STATE_CHARGE_NEAR_FULL: - new_color = LED_GREEN; - break; - case PWR_STATE_ERROR: - new_color = LED_RED; - break; - default: - /* Other states don't change LED color */ - break; - } - - /* - * The power adapter on link can partially unplug and lose its LED - * state. There's no way to detect this, so just assume it forgets its - * state every 10 seconds. - */ - if (!(tick_count % 10)) - current_color = LED_COLOR_COUNT; - - /* If current color is still correct, leave now */ - if (new_color == current_color) - return; - - /* Update LED */ - if (!led_set(new_color)) - current_color = new_color; -} -DECLARE_HOOK(HOOK_SECOND, onewire_led_tick, HOOK_PRIO_DEFAULT); - -/*****************************************************************************/ -/* Console commands */ -#define CONFIG_CMD_POWERLED -static int command_powerled(int argc, char **argv) -{ - int i; - - /* Pick a color, any color... */ - for (i = 0; i < LED_COLOR_COUNT; i++) { - if (!strcasecmp(argv[1], color_names[i])) - return led_set(i); - } - return EC_ERROR_PARAM1; -} -DECLARE_CONSOLE_COMMAND(powerled, command_powerled, - "<off | red | yellow | green>", - "Set power LED color"); -#endif diff --git a/driver/led/lm3509.c b/driver/led/lm3509.c deleted file mode 100644 index 7c20c43ac2..0000000000 --- a/driver/led/lm3509.c +++ /dev/null @@ -1,85 +0,0 @@ -/* Copyright 2018 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. - * - * TI LM3509 LED driver. - */ - -#include "compile_time_macros.h" -#include "i2c.h" -#include "keyboard_backlight.h" -#include "lm3509.h" - -static inline int lm3509_write(uint8_t reg, uint8_t val) -{ - return i2c_write8(I2C_PORT_KBLIGHT, LM3509_I2C_ADDR_FLAGS, - reg, val); -} - -static inline int lm3509_read(uint8_t reg, int *val) -{ - return i2c_read8(I2C_PORT_KBLIGHT, LM3509_I2C_ADDR_FLAGS, - reg, val); -} - -/* Brightness level (0.0 to 100.0%) to brightness register conversion table */ -static const uint16_t lm3509_brightness[32] = { - 0, 1, 6, 10, 11, 13, 16, 20, - 24, 28, 31, 37, 43, 52, 62, 75, - 87, 100, 125, 150, 168, 187, 225, 262, - 312, 375, 437, 525, 612, 700, 875, 1000 -}; - -static int brightness_to_bmain(int percent) -{ - int i; - int b = percent * 10; - - for (i = 1; i < sizeof(lm3509_brightness); i++) { - int low = lm3509_brightness[i - 1]; - int high = lm3509_brightness[i]; - if (high < b) - continue; - /* rounding to the nearest */ - return (b - low < high - b) ? i - 1 : i; - } - /* Brightness is out of range. Return the highest value. */ - return i - 1; -} - -static int lm3509_power(int enable) -{ - /* Enable both MAIN and SUB in unison mode. - * Don't alter brightness here. It's not driver's business. */ - return lm3509_write(LM3509_REG_GP, enable ? 0x7 : 0); -} - -static int lm3509_set_brightness(int percent) -{ - /* We don't need to read/mask/write BMAIN because bit6 and 7 are non - * functional read only bits. - */ - return lm3509_write(LM3509_REG_BMAIN, brightness_to_bmain(percent)); -} - -static int lm3509_get_brightness(void) -{ - int rv, val; - rv = lm3509_read(LM3509_REG_BMAIN, &val); - if (rv) - return -1; - val &= LM3509_BMAIN_MASK; - return lm3509_brightness[val] / 10; -} - -static int lm3509_init(void) -{ - return EC_SUCCESS; -} - -const struct kblight_drv kblight_lm3509 = { - .init = lm3509_init, - .set = lm3509_set_brightness, - .get = lm3509_get_brightness, - .enable = lm3509_power, -}; diff --git a/driver/led/lm3509.h b/driver/led/lm3509.h deleted file mode 100644 index a7defe1fb7..0000000000 --- a/driver/led/lm3509.h +++ /dev/null @@ -1,37 +0,0 @@ -/* Copyright 2018 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. - * - * TI LM3509 LED driver. - */ - -#ifndef __CROS_EC_LM3509_H -#define __CROS_EC_LM3509_H - -#define LM3509_I2C_ADDR_FLAGS 0x36 - -/* - * General purpose register - * - * [2]= set both main and secondary current same - * both control by BMAIN. - * [1]= enable secondary current sink. - * [0]= enable main current sink. - */ -#define LM3509_REG_GP 0x10 - -/* - * Brightness register - * - * 0x00: 0% - * 0x1F: 100% - * Power-on-value: 0% (0xE0) - */ -#define LM3509_REG_BMAIN 0xA0 -#define LM3509_REG_BSUB 0xB0 - -#define LM3509_BMAIN_MASK 0x1F - -extern const struct kblight_drv kblight_lm3509; - -#endif /* __CROS_EC_LM3509_H */ diff --git a/driver/led/lm3630a.c b/driver/led/lm3630a.c deleted file mode 100644 index a2c4aaa74c..0000000000 --- a/driver/led/lm3630a.c +++ /dev/null @@ -1,86 +0,0 @@ -/* Copyright 2018 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. - * - * TI LM3630A LED driver. - */ - -#include "hooks.h" -#include "i2c.h" -#include "lm3630a.h" -#include "timer.h" - - -/* I2C address */ -#define LM3630A_I2C_ADDR_FLAGS 0x36 - -static inline int lm3630a_write(uint8_t reg, uint8_t val) -{ - return i2c_write8(I2C_PORT_KBLIGHT, LM3630A_I2C_ADDR_FLAGS, - reg, val); -} - -static inline int lm3630a_read(uint8_t reg, int *val) -{ - return i2c_read8(I2C_PORT_KBLIGHT, LM3630A_I2C_ADDR_FLAGS, - reg, val); -} - -static void deferred_lm3630a_poweron(void) -{ - /* - * Set full brightness so that PWM will control. This needs to happen - * after setting the control register, because enabling the banks - * resets the value to 0. - */ - lm3630a_write(LM3630A_REG_A_BRIGHTNESS, 0xff); -} -DECLARE_DEFERRED(deferred_lm3630a_poweron); - -int lm3630a_poweron(void) -{ - int ret = 0; - - /* - * LM3630A will NAK I2C transactions for 1ms (tWAIT in the datasheet) - * after HWEN asserted or after SW reset. - */ - msleep(1); - - /* Sample PWM every 8 periods. */ - ret |= lm3630a_write(LM3630A_REG_FILTER_STRENGTH, 0x3); - - /* Enable feedback and PWM for banks A. */ - ret |= lm3630a_write(LM3630A_REG_CONFIG, - LM3630A_CFG_BIT_FB_EN_A | - LM3630A_CFG_BIT_PWM_EN_A); - - /* 24V, 800mA overcurrent protection, 500kHz boost frequency. */ - ret |= lm3630a_write(LM3630A_REG_BOOST_CONTROL, - LM3630A_BOOST_OVP_24V | - LM3630A_BOOST_OCP_800MA | - LM3630A_FMODE_500KHZ); - - /* Limit current to 24.5mA */ - ret |= lm3630a_write(LM3630A_REG_A_CURRENT, 0x1a); - - /* Enable bank A, put in linear mode, and connect LED2 to bank A. */ - ret |= lm3630a_write(LM3630A_REG_CONTROL, - LM3630A_CTRL_BIT_LINEAR_A | - LM3630A_CTRL_BIT_LED_EN_A | - LM3630A_CTRL_BIT_LED2_ON_A); - - /* - * Only set the brightness after ~100 ms. Without this, LED may blink - * for a short duration, as the PWM sampler sometimes appears to be - * confused, and slowly dim from a large initial PWM input value. - */ - hook_call_deferred(&deferred_lm3630a_poweron_data, 100 * MSEC); - - return ret; -} - -int lm3630a_poweroff(void) -{ - return lm3630a_write(LM3630A_REG_CONTROL, LM3630A_CTRL_BIT_SLEEP_CMD); -} diff --git a/driver/led/lm3630a.h b/driver/led/lm3630a.h deleted file mode 100644 index d43304b66e..0000000000 --- a/driver/led/lm3630a.h +++ /dev/null @@ -1,68 +0,0 @@ -/* Copyright 2018 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. - * - * TI LM3630A LED driver. - */ - -#ifndef __CROS_EC_LM3630A_H -#define __CROS_EC_LM3630A_H - -#define LM3630A_REG_CONTROL 0x00 -#define LM3630A_REG_CONFIG 0x01 -#define LM3630A_REG_BOOST_CONTROL 0x02 -#define LM3630A_REG_A_BRIGHTNESS 0x03 -#define LM3630A_REG_B_BRIGHTNESS 0x04 -#define LM3630A_REG_A_CURRENT 0x05 -#define LM3630A_REG_B_CURRENT 0x06 -#define LM3630A_REG_ONOFF_RAMP 0x07 -#define LM3630A_REG_RUN_RAMP 0x08 -#define LM3630A_REG_INT_STATUS 0x09 -#define LM3630A_REG_INT_ENABLE 0x0a -#define LM3630A_REG_FAULT_STATUS 0x0b -#define LM3630A_REG_SW_RESET 0x0f -#define LM3630A_REG_PWM_OUT_LOW 0x12 -#define LM3630A_REG_PWM_OUT_HIGH 0x13 -#define LM3630A_REG_REVISION 0x1f -#define LM3630A_REG_FILTER_STRENGTH 0x50 - -/* Control register bits */ -#define LM3630A_CTRL_BIT_SLEEP_CMD BIT(7) -#define LM3630A_CTRL_BIT_SLEEP_STAT BIT(6) -#define LM3630A_CTRL_BIT_LINEAR_A BIT(4) -#define LM3630A_CTRL_BIT_LINEAR_B BIT(3) -#define LM3630A_CTRL_BIT_LED_EN_A BIT(2) -#define LM3630A_CTRL_BIT_LED_EN_B BIT(1) -#define LM3630A_CTRL_BIT_LED2_ON_A BIT(0) - -/* Config register bits */ -#define LM3630A_CFG_BIT_FB_EN_B BIT(4) -#define LM3630A_CFG_BIT_FB_EN_A BIT(3) -#define LM3630A_CFG_BIT_PWM_LOW BIT(2) -#define LM3630A_CFG_BIT_PWM_EN_B BIT(1) -#define LM3630A_CFG_BIT_PWM_EN_A BIT(0) - -/* Boost control register bits */ -#define LM3630A_BOOST_OVP_16V (0 << 5) -#define LM3630A_BOOST_OVP_24V BIT(5) -#define LM3630A_BOOST_OVP_32V (2 << 5) -#define LM3630A_BOOST_OVP_40V (3 << 5) -#define LM3630A_BOOST_OCP_600MA (0 << 3) -#define LM3630A_BOOST_OCP_800MA BIT(3) -#define LM3630A_BOOST_OCP_1000MA (2 << 3) -#define LM3630A_BOOST_OCP_1200MA (3 << 3) -#define LM3630A_BOOST_SLOW_START BIT(2) -#define LM3630A_SHIFT_500KHZ (0 << 1) /* FMODE=0 */ -#define LM3630A_SHIFT_560KHZ BIT(1) /* FMODE=0 */ -#define LM3630A_SHIFT_1000KHZ (0 << 1) /* FMODE=1 */ -#define LM3630A_SHIFT_1120KHZ BIT(1) /* FMODE=1 */ -#define LM3630A_FMODE_500KHZ (0 << 0) -#define LM3630A_FMODE_1000KHZ BIT(0) - -/* Power on and initialize LM3630A. */ -int lm3630a_poweron(void); - -/* Power off LM3630A. */ -int lm3630a_poweroff(void); - -#endif /* __CROS_EC_LM3630A_H */ diff --git a/driver/led/lp5562.c b/driver/led/lp5562.c deleted file mode 100644 index e0758a8b91..0000000000 --- a/driver/led/lp5562.c +++ /dev/null @@ -1,160 +0,0 @@ -/* Copyright 2013 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. - * - * TI LP5562 driver. - */ - -#include "console.h" -#include "i2c.h" -#include "lp5562.h" -#include "timer.h" -#include "util.h" - -/* I2C address */ -#define LP5562_I2C_ADDR_FLAGS 0x30 - -inline int lp5562_write(uint8_t reg, uint8_t val) -{ - return i2c_write8(I2C_PORT_MASTER, LP5562_I2C_ADDR_FLAGS, reg, val); -} - -inline int lp5562_read(uint8_t reg, int *val) -{ - return i2c_read8(I2C_PORT_MASTER, LP5562_I2C_ADDR_FLAGS, reg, val); -} - -int lp5562_set_color(uint32_t rgb) -{ - int ret = 0; - - ret |= lp5562_write(LP5562_REG_B_PWM, rgb & 0xff); - ret |= lp5562_write(LP5562_REG_G_PWM, (rgb >> 8) & 0xff); - ret |= lp5562_write(LP5562_REG_R_PWM, (rgb >> 16) & 0xff); - - return ret; -} - -int lp5562_set_engine(uint8_t r, uint8_t g, uint8_t b) -{ - return lp5562_write(LP5562_REG_LED_MAP, (r << 4) | (g << 2) | b); -} - -int lp5562_engine_load(int engine, const uint8_t *program, int size) -{ - int prog_addr = LP5562_REG_ENG_PROG(engine); - int i, ret, val; - int shift = 6 - engine * 2; - - ret = lp5562_read(LP5562_REG_OP_MODE, &val); - if (ret) - return ret; - val &= ~(0x3 << shift); - val |= 0x1 << shift; - ret = lp5562_write(LP5562_REG_OP_MODE, val); - if (ret) - return ret; - - for (i = 0; i < size; ++i) { - ret = lp5562_write(prog_addr + i, program[i]); - if (ret) - return ret; - } - - val &= ~(0x3 << shift); - val |= 0x2 << shift; - ret = lp5562_write(LP5562_REG_OP_MODE, val); - - return ret; -} - -int lp5562_engine_control(int eng1, int eng2, int eng3) -{ - int ret, val; - - ret = lp5562_read(LP5562_REG_ENABLE, &val); - if (ret) - return ret; - val &= 0xc0; - val |= (eng1 << 4) | (eng2 << 2) | eng3; - return lp5562_write(LP5562_REG_ENABLE, val); -} - -int lp5562_get_engine_state(int engine) -{ - int val; - - if (lp5562_read(LP5562_REG_ENABLE, &val)) - return 0xee; - return (val >> (6 - engine * 2)) & 0x3; -} - -int lp5562_poweron(void) -{ - int ret = 0; - - ret |= lp5562_write(LP5562_REG_ENABLE, 0x40); - udelay(500); /* start-up delay */ - - ret |= lp5562_write(LP5562_REG_CONFIG, 0x1); - ret |= lp5562_write(LP5562_REG_LED_MAP, 0x0); - - return ret; -} - -int lp5562_poweroff(void) -{ - return lp5562_write(LP5562_REG_ENABLE, 0x0); -} - -int lp5562_get_pc(int engine) -{ - int ret; - if (lp5562_read(LP5562_REG_ENG1_PC + engine - 1, &ret)) - return 0xee; - return ret; -} - -int lp5562_set_pc(int engine, int val) -{ - return lp5562_write(LP5562_REG_ENG1_PC + engine - 1, val); -} - -/*****************************************************************************/ -/* Console commands */ -#ifdef CONFIG_CMD_POWERLED -static int command_lp5562(int argc, char **argv) -{ - if (argc == 4) { - char *e; - uint8_t red, green, blue; - - red = strtoi(argv[1], &e, 0); - if (e && *e) - return EC_ERROR_PARAM1; - green = strtoi(argv[2], &e, 0); - if (e && *e) - return EC_ERROR_PARAM2; - blue = strtoi(argv[3], &e, 0); - if (e && *e) - return EC_ERROR_PARAM3; - - return lp5562_set_color((red << 16) | (green << 8) | blue); - } else if (argc == 2) { - int v; - - if (!parse_bool(argv[1], &v)) - return EC_ERROR_PARAM1; - - if (v) - return lp5562_poweron(); - else - return lp5562_poweroff(); - } - - return EC_ERROR_INVAL; -} -DECLARE_CONSOLE_COMMAND(lp5562, command_lp5562, - "on | off | <red> <green> <blue>", - "Set the color of the LED"); -#endif diff --git a/driver/led/lp5562.h b/driver/led/lp5562.h deleted file mode 100644 index 75e820aab7..0000000000 --- a/driver/led/lp5562.h +++ /dev/null @@ -1,76 +0,0 @@ -/* Copyright 2013 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. - * - * TI LP5562 LED driver. - */ - -#ifndef __CROS_EC_LP5562_H -#define __CROS_EC_LP5562_H - -#define LP5562_REG_ENABLE 0x00 -#define LP5562_REG_OP_MODE 0x01 -#define LP5562_REG_B_PWM 0x02 -#define LP5562_REG_G_PWM 0x03 -#define LP5562_REG_R_PWM 0x04 -#define LP5562_REG_B_CURRENT 0x05 -#define LP5562_REG_G_CURRENT 0x06 -#define LP5562_REG_R_CURRENT 0x07 -#define LP5562_REG_CONFIG 0x08 -#define LP5562_REG_ENG1_PC 0x09 -#define LP5562_REG_ENG2_PC 0x0a -#define LP5562_REG_ENG3_PC 0x0b -#define LP5562_REG_STATUS 0x0c -#define LP5562_REG_RESET 0x0d -#define LP5562_REG_W_PWM 0x0e -#define LP5562_REG_W_CURRENT 0x0f -#define LP5562_REG_LED_MAP 0x70 - -#define LP5562_REG_ENG_PROG(n) (0x10 + ((n)-1) * 0x20) - -/* Brightness range: 0x00 - 0xff */ -#define LP5562_COLOR_NONE 0x000000 -#define LP5562_COLOR_RED(b) (0x010000 * (b)) -#define LP5562_COLOR_GREEN(b) (0x000100 * (b)) -#define LP5562_COLOR_BLUE(b) (0x000001 * (b)) - -#define LP5562_ENG_SEL_NONE 0x0 -#define LP5562_ENG_SEL_1 0x1 -#define LP5562_ENG_SEL_2 0x2 -#define LP5562_ENG_SEL_3 0x3 - -#define LP5562_ENG_HOLD 0x0 -#define LP5562_ENG_STEP 0x1 -#define LP5562_ENG_RUN 0x2 - -/* Power on and initialize LP5562. */ -int lp5562_poweron(void); - -/* Power off LP5562. */ -int lp5562_poweroff(void); - -/* - * Set LED color. - * The parameter 'rgb' is in the format 0x00RRGGBB. - */ -int lp5562_set_color(uint32_t rgb); - -/* Set lighting engine used by each color */ -int lp5562_set_engine(uint8_t r, uint8_t g, uint8_t b); - -/* Load lighting engine program */ -int lp5562_engine_load(int engine, const uint8_t *program, int size); - -/* Control lighting engine execution state */ -int lp5562_engine_control(int eng1, int eng2, int eng3); - -/* Get engine execution state. Return 0xee on error. */ -int lp5562_get_engine_state(int engine); - -/* Get current program counter. Return 0xee on error. */ -int lp5562_get_pc(int engine); - -/* Set program counter */ -int lp5562_set_pc(int engine, int val); - -#endif /* __CROS_EC_LP5562_H */ diff --git a/driver/led/max695x.c b/driver/led/max695x.c deleted file mode 100644 index 6f0e1b8e84..0000000000 --- a/driver/led/max695x.c +++ /dev/null @@ -1,123 +0,0 @@ -/* Copyright 2019 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. - * - * MAX6958/MAX6959 7-Segment LED Display Driver - */ - -#include "common.h" -#include "console.h" -#include "display_7seg.h" -#include "hooks.h" -#include "i2c.h" -#include "max695x.h" -#include "util.h" - -#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args) - -static inline int max695x_i2c_write8(uint8_t offset, uint8_t data) -{ - return i2c_write8(I2C_PORT_PORT80, PORT80_I2C_ADDR, - offset, (int)data); -} - -static inline int max695x_i2c_write(uint8_t offset, uint8_t *data, int len) -{ - /* - * The address pointer stored in the MAX695x increments after - * each data byte is written unless the address equals 01111111 - */ - return i2c_write_block(I2C_PORT_PORT80, PORT80_I2C_ADDR, - offset, data, len); -} - -int display_7seg_write(enum seven_seg_module_display module, uint16_t data) -{ - uint8_t buf[4]; - - /* - * Convert the data into binary coded hexadecimal value i.e. - * in hexadecimal code-decode mode, the decoder prints 1 byte - * on two segments. It checks the lower nibble of the data in - * the digit register (D3–D0), disregarding bits D7–D4. Hence, - * preparing the hexadecimal buffer to be sent. - * - * Segment 3-2 : Module name - * 0xEC : EC - * 0x80 : PORT80 - * Segment 1-0 : Data - * For console Command segment 3-0 : Data - */ - switch (module) { - case SEVEN_SEG_CONSOLE_DISPLAY: - /* Segment - 3 */ - buf[0] = (data >> 12) & 0x0F; - /* Segment - 2 */ - buf[1] = (data >> 8) & 0x0F; - break; - case SEVEN_SEG_EC_DISPLAY: - /* Segment - 3 */ - buf[0] = 0x0E; - /* Segment - 2 */ - buf[1] = 0x0C; - break; - case SEVEN_SEG_PORT80_DISPLAY: - /* Segment - 3 */ - buf[0] = 0x08; - /* Segment - 2 */ - buf[1] = 0x00; - break; - default: - CPRINTS("Unknown Module"); - return EC_ERROR_UNKNOWN; - } - /* Segment - 1 */ - buf[2] = (data >> 4) & 0x0F; - /* Segment - 0 */ - buf[3] = data & 0x0F; - - return max695x_i2c_write(MAX695X_DIGIT0_ADDR, buf, ARRAY_SIZE(buf)); -} - -/** - * Initialise MAX656x 7-segment display. - */ -static void max695x_init(void) -{ - uint8_t buf[4] = { - [0] = MAX695X_DECODE_MODE_HEX_DECODE, - [1] = MAX695X_INTENSITY_MEDIUM, - [2] = MAX695X_SCAN_LIMIT_4, - [3] = MAX695X_CONFIG_OPR_NORMAL - }; - max695x_i2c_write(MAX695X_REG_DECODE_MODE, buf, ARRAY_SIZE(buf)); -} -DECLARE_HOOK(HOOK_INIT, max695x_init, HOOK_PRIO_DEFAULT); - -static void max695x_shutdown(void) -{ - max695x_i2c_write8(MAX695X_REG_CONFIG, - MAX695X_CONFIG_OPR_SHUTDOWN); -} -DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, max695x_shutdown, HOOK_PRIO_DEFAULT); - -#ifdef CONFIG_CMD_SEVEN_SEG_DISPLAY -static int console_command_max695x_write(int argc, char **argv) -{ - char *e; - int val; - - if (argc < 2) - return EC_ERROR_PARAM_COUNT; - - /* Get value to be written to the seven segment display*/ - val = strtoi(argv[1], &e, 0); - if (*e || val < 0 || val > UINT16_MAX) - return EC_ERROR_PARAM1; - - return display_7seg_write(SEVEN_SEG_CONSOLE_DISPLAY, val); -} -DECLARE_CONSOLE_COMMAND(seg, console_command_max695x_write, - "<val>", - "Write to 7 segment display in hex"); -#endif diff --git a/driver/led/max695x.h b/driver/led/max695x.h deleted file mode 100644 index 5ed5d91e2f..0000000000 --- a/driver/led/max695x.h +++ /dev/null @@ -1,44 +0,0 @@ -/* Copyright 2019 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. - * - * MAX6958/MAX6959 7-Segment LED Display Driver header - */ - -#ifndef __CROS_EC_MAX656X_H -#define __CROS_EC_MAX656X_H - -/* I2C interface */ -#define MAX695X_I2C_ADDR1_FLAGS 0x38 -#define MAX695X_I2C_ADDR2_FLAGS 0x39 - -/* Decode mode register */ -#define MAX695X_REG_DECODE_MODE 0x01 -/* Hexadecimal decode for digits 3–0 */ -#define MAX695X_DECODE_MODE_HEX_DECODE 0x0f - -/* Intensity register */ -#define MAX695X_REG_INTENSITY 0x02 -/* Setting meduim intensity */ -#define MAX695X_INTENSITY_MEDIUM 0x20 - -/* Scan limit register value */ -#define MAX695X_REG_SCAN_LIMIT 0x03 - -/* Scanning digits 0-3 */ -#define MAX695X_SCAN_LIMIT_4 0x03 - -/* Configuration register */ -#define MAX695X_REG_CONFIG 0x04 -/* Shutdown seven segment display */ -#define MAX695X_CONFIG_OPR_SHUTDOWN 0x00 -/* Start seven segment display */ -#define MAX695X_CONFIG_OPR_NORMAL 0x01 - -/* Digit addresses */ -#define MAX695X_DIGIT0_ADDR 0x20 -#define MAX695X_DIGIT1_ADDR 0x21 -#define MAX695X_DIGIT2_ADDR 0x22 -#define MAX695X_DIGIT3_ADDR 0x23 - -#endif /* __CROS_EC_MAX656X_H */ diff --git a/driver/led/oz554.c b/driver/led/oz554.c deleted file mode 100644 index fcbbee46ce..0000000000 --- a/driver/led/oz554.c +++ /dev/null @@ -1,145 +0,0 @@ -/* Copyright 2018 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. - * - * O2 Micro OZ554 LED driver. - */ - -#include "console.h" -#include "gpio.h" -#include "hooks.h" -#include "i2c.h" -#include "oz554.h" -#include "task.h" -#include "timer.h" - -#define CPRINTS(format, args...) cprints(CC_I2C, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_I2C, format, ## args) - -#define I2C_ADDR_OZ554_FLAGS 0x31 - -struct oz554_value { - uint8_t offset; - uint8_t data; -}; - -/* - * OZ554ALN asserts the interrupt when it's ready for writing settings, which - * are cleared when it's turned off. We enable the interrupt on HOOK_INIT and - * keep it enabled in S0/S3/S5. - * - * It's assumed the device doesn't have a lid and OZ554ALN is powered only in - * S0. For clamshell devices, different interrupt & power control scheme may be - * needed. - */ - -/* This ordering is suggested by vendor. */ -static struct oz554_value oz554_conf[] = { - /* - * Reigster 0x01: Operation frequency control - * Frequency selection: 300(KHz) - * Short circuit protection: 8(V) - */ - {.offset = 1, .data = 0x43}, - /* - * Reigster 0x02: LED current amplitude control - * ISET Resistor: 10.2(Kohm) - * Maximum LED current: 1636/10.2 = 160.4(mA) - * Setting LED current: 65(mA) - */ - {.offset = 2, .data = 0x65}, - /* - * Reigster 0x03: LED backlight Status - * Status function: Read only - */ - {.offset = 3, .data = 0x00}, - /* - * Reigster 0x04: LED current control with SMBus - * SMBus PWM function: None Use - */ - {.offset = 4, .data = 0x00}, - /* - * Reigster 0x05: OVP, OCP control - * Over Current Protection: 0.5(V) - * Panel LED Voltage(Max): 47.8(V) - * OVP setting: 54(V) - */ - {.offset = 5, .data = 0x97}, - /* - * Reigster 0x00: Dimming mode and string ON/OFF control - * String Selection: 4(Number) - * Interface Selection: 1 - * Brightness mode: 3 - */ - {.offset = 0, .data = 0xF2}, -}; -static const int oz554_conf_size = ARRAY_SIZE(oz554_conf); - -static void set_oz554_reg(void) -{ - int i; - - for (i = 0; i < oz554_conf_size; ++i) { - int rv = i2c_write8(I2C_PORT_BACKLIGHT, - I2C_ADDR_OZ554_FLAGS, - oz554_conf[i].offset, oz554_conf[i].data); - if (rv) { - CPRINTS("Write OZ554 register %d failed rv=%d" , i, rv); - return; - } - } - CPRINTS("Wrote OZ554 settings"); -} - -static void backlight_enable_deferred(void) -{ - if (gpio_get_level(GPIO_PANEL_BACKLIGHT_EN)) - set_oz554_reg(); -} -DECLARE_DEFERRED(backlight_enable_deferred); - -void backlight_enable_interrupt(enum gpio_signal signal) -{ - /* - * 1. Spec says backlight should be turned on after 500ms - * after eDP signals are ready. - * - * 2. There's no way to get exact eDP ready time, therefore, - * give one second delay. - * - * power up __/---------------- - * eDP ______/------------ - * backlight _____________/----- - * |- t1 -| : >=500 ms - * |- t2 -| : 1 second is enough - */ - hook_call_deferred(&backlight_enable_deferred_data, - OZ554_POWER_BACKLIGHT_DELAY); -} - -int oz554_set_config(int offset, int data) -{ - int i; - for (i = 0; i < oz554_conf_size; i++) { - if (oz554_conf[i].offset == offset) - break; - } - if (i >= oz554_conf_size) - /* Matching offset not found */ - return EC_ERROR_INVAL; - oz554_conf[i].data = data; - return EC_SUCCESS; -} - -static void init_oz554(void) -{ - oz554_board_init(); - - gpio_enable_interrupt(GPIO_PANEL_BACKLIGHT_EN); -} -DECLARE_HOOK(HOOK_INIT, init_oz554, HOOK_PRIO_DEFAULT); - - -__overridable void oz554_board_init(void) -{ -} diff --git a/driver/led/oz554.h b/driver/led/oz554.h deleted file mode 100644 index d1d9d9656e..0000000000 --- a/driver/led/oz554.h +++ /dev/null @@ -1,35 +0,0 @@ -/* Copyright 2018 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. - * - * O2 Micro OZ554 LED driver. - */ - -#ifndef __CROS_EC_OZ554_H -#define __CROS_EC_OZ554_H - -#include "gpio.h" -#include "common.h" - -/* - * Overridable board initialization. Should be overridden by a board - * specific function if the default is not appropriate - */ -__override_proto void oz554_board_init(void); - -/** - * Update oz554 configuration array (oz554_conf). - * - * @param offset: Offset of the register to be set. - * @param data: Value to be set. - * @return EC_SUCCESS or EC_ERROR_* for errors. - */ -int oz554_set_config(int offset, int data); - -#ifndef OZ554_POWER_BACKLIGHT_DELAY -#define OZ554_POWER_BACKLIGHT_DELAY SECOND -#endif - -void backlight_enable_interrupt(enum gpio_signal signal); - -#endif diff --git a/driver/mag_bmm150.c b/driver/mag_bmm150.c deleted file mode 100644 index ae1c736540..0000000000 --- a/driver/mag_bmm150.c +++ /dev/null @@ -1,268 +0,0 @@ -/* 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. - */ - -/** - * BMM150 compass behind a BMI160 - */ - -#include "accelgyro.h" -#include "common.h" -#include "console.h" -#include "driver/mag_bmm150.h" -#include "hooks.h" -#include "i2c.h" -#include "task.h" -#include "timer.h" -#include "util.h" - -#ifdef CONFIG_MAG_BMI160_BMM150 -#include "driver/accelgyro_bmi160.h" -#define raw_mag_read8 bmi160_sec_raw_read8 -#define raw_mag_write8 bmi160_sec_raw_write8 -#else -#error "Not implemented" -#endif - - -#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) - - -/**************************************************************************** -* Copyright (C) 2011 - 2014 Bosch Sensortec GmbH -* -****************************************************************************/ -/*************************************************************************** -* License: -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* -* Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* -* Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* -* Neither the name of the copyright holder nor the names of the -* contributors may be used to endorse or promote products derived from -* this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE -* -* The information provided is believed to be accurate and reliable. -* The copyright holder assumes no responsibility for the consequences of use -* of such information nor for any infringement of patents or -* other rights of third parties which may result from its use. -* No license is granted by implication or otherwise under any patent or -* patent rights of the copyright holder. -*/ - -#define BMI150_READ_16BIT_COM_REG(store_, addr_) do { \ - int val; \ - raw_mag_read8(s->port, s->i2c_spi_addr_flags, (addr_), &val); \ - store_ = val; \ - raw_mag_read8(s->port, s->i2c_spi_addr_flags, (addr_) + 1, &val); \ - store_ |= (val << 8); \ -} while (0) - - -int bmm150_init(const struct motion_sensor_t *s) -{ - int ret; - int val; - struct bmm150_comp_registers *regs = BMM150_COMP_REG(s); - struct mag_cal_t *moc = BMM150_CAL(s); - - /* Set the compass from Suspend to Sleep */ - ret = raw_mag_write8(s->port, s->i2c_spi_addr_flags, - BMM150_PWR_CTRL, BMM150_PWR_ON); - msleep(4); - /* Now we can read the device id */ - ret = raw_mag_read8(s->port, s->i2c_spi_addr_flags, - BMM150_CHIP_ID, &val); - if (ret) - return EC_ERROR_UNKNOWN; - - if (val != BMM150_CHIP_ID_MAJOR) - return EC_ERROR_ACCESS_DENIED; - - /* Read the private registers for compensation */ - ret = raw_mag_read8(s->port, s->i2c_spi_addr_flags, - BMM150_REGA_DIG_X1, &val); - if (ret) - return EC_ERROR_UNKNOWN; - regs->dig1[X] = val; - raw_mag_read8(s->port, s->i2c_spi_addr_flags, - BMM150_REGA_DIG_Y1, &val); - regs->dig1[Y] = val; - raw_mag_read8(s->port, s->i2c_spi_addr_flags, - BMM150_REGA_DIG_X2, &val); - regs->dig2[X] = val; - raw_mag_read8(s->port, s->i2c_spi_addr_flags, - BMM150_REGA_DIG_Y2, &val); - regs->dig2[Y] = val; - - raw_mag_read8(s->port, s->i2c_spi_addr_flags, - BMM150_REGA_DIG_XY1, &val); - regs->dig_xy1 = val; - - raw_mag_read8(s->port, s->i2c_spi_addr_flags, - BMM150_REGA_DIG_XY2, &val); - regs->dig_xy2 = val; - - BMI150_READ_16BIT_COM_REG(regs->dig_z1, BMM150_REGA_DIG_Z1_LSB); - BMI150_READ_16BIT_COM_REG(regs->dig_z2, BMM150_REGA_DIG_Z2_LSB); - BMI150_READ_16BIT_COM_REG(regs->dig_z3, BMM150_REGA_DIG_Z3_LSB); - BMI150_READ_16BIT_COM_REG(regs->dig_z4, BMM150_REGA_DIG_Z4_LSB); - BMI150_READ_16BIT_COM_REG(regs->dig_xyz1, BMM150_REGA_DIG_XYZ1_LSB); - - - /* Set the repetition in "Regular Preset" */ - raw_mag_write8(s->port, s->i2c_spi_addr_flags, - BMM150_REPXY, BMM150_REP(SPECIAL, XY)); - raw_mag_write8(s->port, s->i2c_spi_addr_flags, - BMM150_REPZ, BMM150_REP(SPECIAL, Z)); - ret = raw_mag_read8(s->port, s->i2c_spi_addr_flags, - BMM150_REPXY, &val); - ret = raw_mag_read8(s->port, s->i2c_spi_addr_flags, - BMM150_REPZ, &val); - /* - * Set the compass forced mode, to sleep after each measure. - */ - ret = raw_mag_write8(s->port, s->i2c_spi_addr_flags, - BMM150_OP_CTRL, - BMM150_OP_MODE_FORCED << BMM150_OP_MODE_OFFSET); - - init_mag_cal(moc); - moc->radius = 0.0f; - return ret; -} - -void bmm150_temp_compensate_xy(const struct motion_sensor_t *s, - intv3_t raw, - intv3_t comp, - int r) -{ - int inter, axis; - struct bmm150_comp_registers *regs = BMM150_COMP_REG(s); - if (r == 0) - inter = 0; - else - inter = ((int)regs->dig_xyz1 << 14) / r - BIT(14); - - for (axis = X; axis <= Y; axis++) { - if (raw[axis] == BMM150_FLIP_OVERFLOW_ADCVAL) { - comp[axis] = BMM150_OVERFLOW_OUTPUT; - continue; - } - /* - * The formula is, using 4 LSB for precision: - * (mdata_x * ((((dig_xy2 * i^2 / 268435456) + - * i * dig_xy1) / 16384) + 256) * - * (dig2 + 160)) / 8192 + dig1 * 8.0f - * To prevent precision loss, we calculate at << 12: - * 1 / 268435456 = 1 >> 28 = 1 >> (7 + 9 + 12) - * 1 / 16384 = 1 >> (-7 + 9 + 12) - * 256 = 1 << (20 - 12) - */ - comp[axis] = (int)regs->dig_xy2 * ((inter * inter) >> 7); - comp[axis] += inter * ((int)regs->dig_xy1 << 7); - comp[axis] >>= 9; - comp[axis] += 1 << (8 + 12); - comp[axis] *= (int)regs->dig2[axis] + 160; - comp[axis] >>= 12; - comp[axis] *= raw[axis]; - comp[axis] >>= 13; - comp[axis] += (int)regs->dig1[axis] << 3; - } -} - -void bmm150_temp_compensate_z(const struct motion_sensor_t *s, - intv3_t raw, - intv3_t comp, - int r) -{ - int dividend, divisor; - struct bmm150_comp_registers *regs = BMM150_COMP_REG(s); - - if (raw[Z] == BMM150_HALL_OVERFLOW_ADCVAL) { - comp[Z] = BMM150_OVERFLOW_OUTPUT; - return; - } - /* - * The formula is - * ((z - dig_z4) * 131072 - dig_z3 * (r - dig_xyz1)) / - * ((dig_z2 + dig_z1 * r / 32768) * 4); - * - * We spread 4 so we multiply by 131072 / 4 == BIT(15) only. - */ - dividend = (raw[Z] - (int)regs->dig_z4) << 15; - dividend -= (regs->dig_z3 * (r - (int)regs->dig_xyz1)) >> 2; - /* add BIT(15) to round to next integer. */ - divisor = (int)regs->dig_z1 * (r << 1) + BIT(15); - divisor >>= 16; - divisor += (int)regs->dig_z2; - comp[Z] = dividend / divisor; - if (comp[Z] > BIT(15) || comp[Z] < -(BIT(15))) - comp[Z] = BMM150_OVERFLOW_OUTPUT; -} - -void bmm150_normalize(const struct motion_sensor_t *s, - intv3_t v, - uint8_t *data) -{ - uint16_t r; - intv3_t raw; - struct mag_cal_t *cal = BMM150_CAL(s); - - /* X and Y are two's complement 13 bits vectors */ - raw[X] = ((int16_t)(data[0] | (data[1] << 8))) >> 3; - raw[Y] = ((int16_t)(data[2] | (data[3] << 8))) >> 3; - /* X and Y are two's complement 15 bits vectors */ - raw[Z] = ((int16_t)(data[4] | (data[5] << 8))) >> 1; - - /* RHALL value to compensate with - unsigned 14 bits */ - r = (data[6] | (data[7] << 8)) >> 2; - - bmm150_temp_compensate_xy(s, raw, v, r); - bmm150_temp_compensate_z(s, raw, v, r); - mag_cal_update(cal, v); - - v[X] += cal->bias[X]; - v[Y] += cal->bias[Y]; - v[Z] += cal->bias[Z]; -} - -int bmm150_set_offset(const struct motion_sensor_t *s, - const intv3_t offset) -{ - struct mag_cal_t *cal = BMM150_CAL(s); - cal->bias[X] = offset[X]; - cal->bias[Y] = offset[Y]; - cal->bias[Z] = offset[Z]; - return EC_SUCCESS; -} - -int bmm150_get_offset(const struct motion_sensor_t *s, - intv3_t offset) -{ - struct mag_cal_t *cal = BMM150_CAL(s); - offset[X] = cal->bias[X]; - offset[Y] = cal->bias[Y]; - offset[Z] = cal->bias[Z]; - return EC_SUCCESS; -} diff --git a/driver/mag_bmm150.h b/driver/mag_bmm150.h deleted file mode 100644 index 79c77e66d7..0000000000 --- a/driver/mag_bmm150.h +++ /dev/null @@ -1,147 +0,0 @@ -/* 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. - */ - -/* BMM150 magnetometer definition */ - -#ifndef __CROS_EC_MAG_BMM150_H -#define __CROS_EC_MAG_BMM150_H - -#include "accelgyro.h" -#include "mag_cal.h" - -#define BMM150_ADDR0_FLAGS 0x10 -#define BMM150_ADDR1_FLAGS 0x11 -#define BMM150_ADDR2_FLAGS 0x12 -#define BMM150_ADDR3_FLAGS 0x13 - -#define BMM150_CHIP_ID 0x40 -#define BMM150_CHIP_ID_MAJOR 0x32 - -#define BMM150_BASE_DATA 0x42 - -#define BMM150_INT_STATUS 0x4a -#define BMM150_PWR_CTRL 0x4b -#define BMM150_SRST (BIT(7) | BIT(1)) -#define BMM150_PWR_ON BIT(0) - -#define BMM150_OP_CTRL 0x4c -#define BMM150_OP_MODE_OFFSET 1 -#define BMM150_OP_MODE_MASK 3 -#define BMM150_OP_MODE_NORMAL 0x00 -#define BMM150_OP_MODE_FORCED 0x01 -#define BMM150_OP_MODE_SLEEP 0x03 - -#define BMM150_INT_CTRL 0x4d - -#define BMM150_REPXY 0x51 -#define BMM150_LOW_POWER_nXY 3 -#define BMM150_REGULAR_nXY 9 -#define BMM150_ENHANCED_nXY 15 -#define BMM150_HIGH_ACCURACY_nXY 47 -#define BMM150_SPECIAL_nXY 75 -#define BMM150_REPZ 0x52 -#define BMM150_LOW_POWER_nZ 3 -#define BMM150_REGULAR_nZ 15 -#define BMM150_ENHANCED_nZ 27 -#define BMM150_HIGH_ACCURACY_nZ 83 -#define BMM150_SPECIAL_nZ 27 - -#define BMM150_REP(_preset, _axis) CONCAT4(BMM150_, _preset, _n, _axis) - -/* Hidden registers for RHALL calculation */ -#define BMM150_REGA_DIG_X1 0x5d -#define BMM150_REGA_DIG_Y1 0x5e -#define BMM150_REGA_DIG_Z4_LSB 0x62 -#define BMM150_REGA_DIG_Z4_MSB 0x63 -#define BMM150_REGA_DIG_X2 0x64 -#define BMM150_REGA_DIG_Y2 0x65 -#define BMM150_REGA_DIG_Z2_LSB 0x68 -#define BMM150_REGA_DIG_Z2_MSB 0x69 -#define BMM150_REGA_DIG_Z1_LSB 0x6a -#define BMM150_REGA_DIG_Z1_MSB 0x6b -#define BMM150_REGA_DIG_XYZ1_LSB 0x6c -#define BMM150_REGA_DIG_XYZ1_MSB 0x6d -#define BMM150_REGA_DIG_Z3_LSB 0x6e -#define BMM150_REGA_DIG_Z3_MSB 0x6f -#define BMM150_REGA_DIG_XY2 0x70 -#define BMM150_REGA_DIG_XY1 0x71 - -/* Overflow */ - -#define BMM150_FLIP_OVERFLOW_ADCVAL (-4096) -#define BMM150_HALL_OVERFLOW_ADCVAL (-16384) -#define BMM150_OVERFLOW_OUTPUT (0x8000) - -/* Min and Max sampling frequency in mHz */ -#define BMM150_MAG_MIN_FREQ 781 - -/* - * From Section 4.2.4, max frequency depends on the preset. - * - * Fmax ~= 1 / (145us * nXY + 500us * nZ + 980us) - * - * To be safe, declare only 75% of the value. - */ -#define __BMM150_MAG_MAX_FREQ(_preset) (750000000 / \ - (145 * BMM150_REP(_preset, XY) + 500 * BMM150_REP(_preset, Z) + 980)) - -#if (__BMM150_MAG_MAX_FREQ(SPECIAL) > CONFIG_EC_MAX_SENSOR_FREQ_MILLIHZ) -#error "EC too slow for magnetometer" -#endif - -struct bmm150_comp_registers { - /* Local copy of the compensation registers. */ - int8_t dig1[2]; - int8_t dig2[2]; - - uint16_t dig_z1; - int16_t dig_z2; - int16_t dig_z3; - int16_t dig_z4; - - uint8_t dig_xy1; - int8_t dig_xy2; - - uint16_t dig_xyz1; -}; - -struct bmm150_private_data { - /* lsm6dsm_data union requires cal be first element */ - struct mag_cal_t cal; - struct bmm150_comp_registers comp; -}; -#define BMM150_COMP_REG(_s) \ - (&BMI160_GET_DATA(_s)->compass.comp) - -#define BMM150_CAL(_s) \ - (&BMI160_GET_DATA(_s)->compass.cal) - -#ifdef CONFIG_MAG_BMI160_BMM150 -#include "accelgyro_bmi160.h" -/* - * Behind a BMI160, the BMM150 is in forced mode. Be sure to choose a frequency - * comptible with BMI160. - */ -#define BMM150_MAG_MAX_FREQ(_preset) \ - BMI160_REG_TO_ODR(BMI160_ODR_TO_REG(__BMM150_MAG_MAX_FREQ(_preset))) -#else -#define BMM150_MAG_MAX_FREQ(_preset) __BMM150_MAG_MAX_FREQ(_preset) -#endif - -/* Specific initialization of BMM150 when behing BMI160 */ -int bmm150_init(const struct motion_sensor_t *s); - -/* Command to normalize and apply temperature compensation */ -void bmm150_normalize(const struct motion_sensor_t *s, - intv3_t v, - uint8_t *data); - -int bmm150_set_offset(const struct motion_sensor_t *s, - const intv3_t offset); - -int bmm150_get_offset(const struct motion_sensor_t *s, - intv3_t offset); - -#endif /* __CROS_EC_MAG_BMM150_H */ diff --git a/driver/mag_lis2mdl.c b/driver/mag_lis2mdl.c deleted file mode 100644 index c63cb7b971..0000000000 --- a/driver/mag_lis2mdl.c +++ /dev/null @@ -1,402 +0,0 @@ -/* Copyright 2018 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. - */ - -/** - * LIS2MDL magnetometer module for Chrome EC. - * This driver supports LIS2MDL magnetometer in cascade with LSM6DSx (x stands - * for L or M) accel/gyro module. - */ - -#include "common.h" -#include "driver/mag_lis2mdl.h" -#include "driver/sensorhub_lsm6dsm.h" -#include "driver/accelgyro_lsm6dsm.h" -#include "driver/stm_mems_common.h" -#include "hwtimer.h" -#include "mag_cal.h" -#include "task.h" - -#ifdef CONFIG_MAG_LSM6DSM_LIS2MDL -#ifndef CONFIG_SENSORHUB_LSM6DSM -#error "Need Sensor Hub LSM6DSM support" -#endif -#endif - -#define CPRINTF(format, args...) cprintf(CC_ACCEL, format, ## args) - -void lis2mdl_normalize(const struct motion_sensor_t *s, - intv3_t v, - uint8_t *raw) -{ - struct mag_cal_t *cal = LIS2MDL_CAL(s); - int i; -#ifdef CONFIG_MAG_BMI160_LIS2MDL - struct lis2mdl_private_data *private = LIS2MDL_DATA(s); - intv3_t hn1; - - hn1[X] = ((int16_t)((raw[1] << 8) | raw[0])); - hn1[Y] = ((int16_t)((raw[3] << 8) | raw[2])); - hn1[Z] = ((int16_t)((raw[5] << 8) | raw[4])); - - /* Only when LIS2MDL is in forced mode */ - if (private->hn_valid) { - for (i = X; i <= Z; i++) - v[i] = (hn1[i] + private->hn[i]) / 2; - memcpy(private->hn, hn1, sizeof(intv3_t)); - } else { - private->hn_valid = 1; - memcpy(v, hn1, sizeof(intv3_t)); - } -#else - v[X] = ((int16_t)((raw[1] << 8) | raw[0])); - v[Y] = ((int16_t)((raw[3] << 8) | raw[2])); - v[Z] = ((int16_t)((raw[5] << 8) | raw[4])); -#endif - for (i = X; i <= Z; i++) - v[i] = LIS2MDL_RATIO(v[i]); - - mag_cal_update(cal, v); - - v[X] += cal->bias[X]; - v[Y] += cal->bias[Y]; - v[Z] += cal->bias[Z]; -} - -static int set_range(const struct motion_sensor_t *s, int range, int rnd) -{ - struct stprivate_data *data = s->drv_data; - - /* Range is fixed by hardware */ - if (range != s->default_range) - return EC_ERROR_INVAL; - - data->base.range = range; - return EC_SUCCESS; -} - -static int get_range(const struct motion_sensor_t *s) -{ - struct stprivate_data *data = s->drv_data; - - return data->base.range; -} - -/** - * set_offset - Set data offset - * @s: Motion sensor pointer - * @offset: offset vector - * @temp: Temp - */ -static int set_offset(const struct motion_sensor_t *s, - const int16_t *offset, int16_t temp) -{ - struct mag_cal_t *cal = LIS2MDL_CAL(s); - - cal->bias[X] = offset[X]; - cal->bias[Y] = offset[Y]; - cal->bias[Z] = offset[Z]; - rotate_inv(cal->bias, *s->rot_standard_ref, cal->bias); - return EC_SUCCESS; -} - -/** - * get_offset - Get data offset - * @s: Motion sensor pointer - * @offset: offset vector - * @temp: Temp - */ -static int get_offset(const struct motion_sensor_t *s, - int16_t *offset, int16_t *temp) -{ - struct mag_cal_t *cal = LIS2MDL_CAL(s); - intv3_t offset_int; - - rotate(cal->bias, *s->rot_standard_ref, offset_int); - offset[X] = offset_int[X]; - offset[Y] = offset_int[Y]; - offset[Z] = offset_int[Z]; - *temp = EC_MOTION_SENSE_INVALID_CALIB_TEMP; - return EC_SUCCESS; -} - -#ifdef CONFIG_MAG_LSM6DSM_LIS2MDL -int lis2mdl_thru_lsm6dsm_read(const struct motion_sensor_t *s, intv3_t v) -{ - int ret; - uint8_t raw[OUT_XYZ_SIZE]; - /* - * This is mostly for debugging, read happens through LSM6DSM/BMI160 - * FIFO. - */ - mutex_lock(s->mutex); - ret = sensorhub_slv0_data_read(LSM6DSM_MAIN_SENSOR(s), raw); - mutex_unlock(s->mutex); - lis2mdl_normalize(s, v, raw); - rotate(v, *s->rot_standard_ref, v); - return ret; -} - -int lis2mdl_thru_lsm6dsm_init(const struct motion_sensor_t *s) -{ - int ret = EC_ERROR_UNIMPLEMENTED; - struct mag_cal_t *cal = LIS2MDL_CAL(s); - struct stprivate_data *data = s->drv_data; - - mutex_lock(s->mutex); - /* Magnetometer in cascade mode */ - ret = sensorhub_check_and_rst( - LSM6DSM_MAIN_SENSOR(s), - CONFIG_ACCELGYRO_SEC_ADDR_FLAGS, - LIS2MDL_WHO_AM_I_REG, LIS2MDL_WHO_AM_I, - LIS2MDL_CFG_REG_A_ADDR, LIS2MDL_FLAG_SW_RESET); - if (ret != EC_SUCCESS) - goto err_unlock; - - ret = sensorhub_config_ext_reg( - LSM6DSM_MAIN_SENSOR(s), - CONFIG_ACCELGYRO_SEC_ADDR_FLAGS, - LIS2MDL_CFG_REG_A_ADDR, - LIS2MDL_ODR_50HZ | LIS2MDL_MODE_CONT); - if (ret != EC_SUCCESS) - goto err_unlock; - - ret = sensorhub_config_slv0_read( - LSM6DSM_MAIN_SENSOR(s), - CONFIG_ACCELGYRO_SEC_ADDR_FLAGS, - LIS2MDL_OUT_REG, OUT_XYZ_SIZE); - if (ret != EC_SUCCESS) - goto err_unlock; - - mutex_unlock(s->mutex); - init_mag_cal(cal); - cal->radius = 0.0f; - data->resol = LIS2DSL_RESOLUTION; - return sensor_init_done(s); - -err_unlock: - mutex_unlock(s->mutex); - return ret; -} - -#else /* END: CONFIG_MAG_LSM6DSM_LIS2MDL */ - -/** - * Checks whether or not data is ready. If the check succeeds EC_SUCCESS will be - * returned and the ready target written with the axes that are available, see: - * <ul> - * <li>LIS2MDL_X_DIRTY</li> - * <li>LIS2MDL_Y_DIRTY</li> - * <li>LIS2MDL_Z_DIRTY</li> - * <li>LIS2MDL_XYZ_DIRTY</li> - * </ul> - * - * @param s Motion sensor pointer - * @param[out] ready Writeback pointer to store the result. - * @return EC_SUCCESS when the status register was read successfully. - */ -static int lis2mdl_is_data_ready(const struct motion_sensor_t *s, int *ready) -{ - int ret, tmp; - - ret = st_raw_read8(s->port, s->i2c_spi_addr_flags, - LIS2MDL_STATUS_REG, &tmp); - if (ret != EC_SUCCESS) { - *ready = 0; - return ret; - } - - *ready = tmp & LIS2MDL_XYZ_DIRTY_MASK; - return EC_SUCCESS; - -} - -/** - * Read the most recent data from the sensor. If no new data is available, - * simply return the last available values. - * - * @param s Motion sensor pointer - * @param v A vector of 3 ints for x, y, z values. - * @return EC_SUCCESS when the values were read successfully or no new data was - * available. - */ -int lis2mdl_read(const struct motion_sensor_t *s, intv3_t v) -{ - int ret = EC_SUCCESS, ready = 0; - uint8_t raw[OUT_XYZ_SIZE]; - - ret = lis2mdl_is_data_ready(s, &ready); - if (ret != EC_SUCCESS) - return ret; - - /* - * If sensor data is not ready, return the previous read data. - * Note: return success so that the motion sensor task can read again to - * get the latest updated sensor data quickly. - */ - if (!ready) { - if (v != s->raw_xyz) - memcpy(v, s->raw_xyz, sizeof(intv3_t)); - return ret; - } - - mutex_lock(s->mutex); - ret = st_raw_read_n(s->port, s->i2c_spi_addr_flags, - LIS2MDL_OUT_REG, raw, OUT_XYZ_SIZE); - mutex_unlock(s->mutex); - if (ret == EC_SUCCESS) { - lis2mdl_normalize(s, v, raw); - rotate(v, *s->rot_standard_ref, v); - } - return ret; -} - -/** - * Initialize the sensor. This function will verify the who-am-I register - */ -int lis2mdl_init(const struct motion_sensor_t *s) -{ - int ret = EC_ERROR_UNKNOWN, who_am_i, count = LIS2MDL_STARTUP_MS; - struct stprivate_data *data = s->drv_data; - struct mag_cal_t *cal = LIS2MDL_CAL(s); - - /* Check who am I value */ - do { - ret = st_raw_read8(s->port, LIS2MDL_ADDR_FLAGS, - LIS2MDL_WHO_AM_I_REG, &who_am_i); - if (ret != EC_SUCCESS) { - /* Make sure we wait for the chip to start up. Sleep 1ms - * and try again. - */ - udelay(10); - count--; - } else { - break; - } - } while (count > 0); - if (ret != EC_SUCCESS) - return ret; - if (who_am_i != LIS2MDL_WHO_AM_I) - return EC_ERROR_ACCESS_DENIED; - - mutex_lock(s->mutex); - - /* Reset the sensor */ - ret = st_raw_write8(s->port, LIS2MDL_ADDR_FLAGS, - LIS2MDL_CFG_REG_A_ADDR, - LIS2MDL_FLAG_SW_RESET); - if (ret != EC_SUCCESS) - goto lis2mdl_init_error; - - mutex_unlock(s->mutex); - - if (ret != EC_SUCCESS) - return ret; - - init_mag_cal(cal); - cal->radius = 0.0f; - data->resol = LIS2DSL_RESOLUTION; - return sensor_init_done(s); - -lis2mdl_init_error: - mutex_unlock(s->mutex); - return ret; -} - -/** - * Set the data rate of the sensor. Use a rate of 0 or below to turn off the - * magnetometer. All other values will turn on the sensor in continuous mode. - * The rate will be set to the nearest available value: - * <ul> - * <li>LIS2MDL_ODR_10HZ</li> - * <li>LIS2MDL_ODR_20HZ</li> - * <li>LIS2MDL_ODR_50HZ</li> - * </ul> - * - * @param s Motion sensor pointer - * @param rate Rate (mHz) - * @param rnd Flag used to tell whether or not to round up (1) or down (0) - * @return EC_SUCCESS when the rate was successfully changed. - */ -int lis2mdl_set_data_rate(const struct motion_sensor_t *s, int rate, int rnd) -{ - int ret = EC_SUCCESS, normalized_rate = 0; - uint8_t reg_val = 0; - struct mag_cal_t *cal = LIS2MDL_CAL(s); - struct stprivate_data *data = s->drv_data; - - if (rate > 0) { - if (rnd) - /* Round up */ - reg_val = rate <= 10000 ? LIS2MDL_ODR_10HZ - : rate <= 20000 ? LIS2MDL_ODR_20HZ - : LIS2MDL_ODR_50HZ; - else - /* Round down */ - reg_val = rate < 20000 ? LIS2MDL_ODR_10HZ - : rate < 50000 ? LIS2MDL_ODR_20HZ - : LIS2MDL_ODR_50HZ; - } - - normalized_rate = rate <= 0 ? 0 - : reg_val == LIS2MDL_ODR_10HZ ? 10000 - : reg_val == LIS2MDL_ODR_20HZ ? 20000 - : 50000; - - /* - * If no change is needed just bail. Not doing so will require a reset - * of the chip which only leads to re-calibration and lost samples. - */ - if (normalized_rate == data->base.odr) - return ret; - - init_mag_cal(cal); - - if (normalized_rate > 0) - cal->batch_size = MAX( - MAG_CAL_MIN_BATCH_SIZE, - (normalized_rate * 1000) / - MAG_CAL_MIN_BATCH_WINDOW_US); - else - cal->batch_size = 0; - - mutex_lock(s->mutex); - if (rate <= 0) { - ret = st_raw_write8(s->port, LIS2MDL_ADDR_FLAGS, - LIS2MDL_CFG_REG_A_ADDR, - LIS2MDL_FLAG_SW_RESET); - } else { - /* Add continuous and temp compensation flags */ - reg_val |= LIS2MDL_MODE_CONT | LIS2MDL_FLAG_TEMP_COMPENSATION; - ret = st_raw_write8(s->port, LIS2MDL_ADDR_FLAGS, - LIS2MDL_CFG_REG_A_ADDR, reg_val); - } - - mutex_unlock(s->mutex); - - if (ret == EC_SUCCESS) - data->base.odr = normalized_rate; - - return ret; -} - -#endif /* CONFIG_MAG_LIS2MDL */ - -const struct accelgyro_drv lis2mdl_drv = { -#ifdef CONFIG_MAG_LSM6DSM_LIS2MDL - .init = lis2mdl_thru_lsm6dsm_init, - .read = lis2mdl_thru_lsm6dsm_read, - .set_data_rate = lsm6dsm_set_data_rate, -#else /* CONFIG_MAG_LSM6DSM_LIS2MDL */ - .init = lis2mdl_init, - .read = lis2mdl_read, - .set_data_rate = lis2mdl_set_data_rate, -#endif /* !CONFIG_MAG_LSM6DSM_LIS2MDL */ - .set_range = set_range, - .get_range = get_range, - .get_data_rate = st_get_data_rate, - .get_resolution = st_get_resolution, - .set_offset = set_offset, - .get_offset = get_offset, -}; diff --git a/driver/mag_lis2mdl.h b/driver/mag_lis2mdl.h deleted file mode 100644 index 6be0d70e54..0000000000 --- a/driver/mag_lis2mdl.h +++ /dev/null @@ -1,94 +0,0 @@ -/* Copyright 2018 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. - */ - -/* LIS2MSL magnetometer module for Chrome EC */ - -#ifndef __CROS_EC_MAG_LIS2MDL_H -#define __CROS_EC_MAG_LIS2MDL_H - -#include "accelgyro.h" -#include "mag_cal.h" -#include "stm_mems_common.h" - -/* - * 8-bit address is 0011110Wb where the last bit represents whether the - * operation is a read or a write. - */ -#define LIS2MDL_ADDR_FLAGS 0x1e - -#define LIS2MDL_STARTUP_MS 10 - -/* Registers */ -#define LIS2MDL_WHO_AM_I_REG 0x4f -#define LIS2MDL_CFG_REG_A_ADDR 0x60 -#define LIS2MDL_INT_CTRL_REG 0x63 -#define LIS2MDL_STATUS_REG 0x67 -#define LIS2MDL_OUT_REG 0x68 - -#define LIS2MDL_WHO_AM_I 0x40 - -#define LIS2MDL_FLAG_TEMP_COMPENSATION 0x80 -#define LIS2MDL_FLAG_REBOOT 0x40 -#define LIS2MDL_FLAG_SW_RESET 0x20 -#define LIS2MDL_FLAG_LOW_POWER 0x10 -#define LIS2MDL_ODR_50HZ 0x08 -#define LIS2MDL_ODR_20HZ 0x04 -#define LIS2MDL_ODR_10HZ 0x00 -#define LIS2MDL_MODE_IDLE 0x03 -#define LIS2MDL_MODE_SINGLE 0x01 -#define LIS2MDL_MODE_CONT 0x00 -#define LIS2MDL_ODR_MODE_MASK 0x8f - -#define LIS2MDL_X_DIRTY 0x01 -#define LIS2MDL_Y_DIRTY 0x02 -#define LIS2MDL_Z_DIRTY 0x04 -#define LIS2MDL_XYZ_DIRTY 0x08 -#define LIS2MDL_XYZ_DIRTY_MASK 0x0f - -#define LIS2DSL_RESOLUTION 16 -/* - * Maximum sensor data range (milligauss): - * Spec is 1.5 mguass / LSB, so 0.15 uT / LSB. - * Calibration code is set to 16LSB/ut, [0.0625 uT/LSB] - * Apply a multiplier to change the unit - */ -#define LIS2MDL_RATIO(_in) (((_in) * 24) / 10) - -struct lis2mdl_private_data { - /* lsm6dsm_data union requires cal be first element */ - struct mag_cal_t cal; -#ifndef CONFIG_LSM6DSM_SEC_I2C - struct stprivate_data data; -#endif -#ifdef CONFIG_MAG_BMI160_LIS2MDL - intv3_t hn; /* last sample for offset compensation */ - int hn_valid; -#endif -}; - -#ifndef CONFIG_LSM6DSM_SEC_I2C -#define LIS2MDL_ST_DATA(g) (&((g).data)) - -#ifdef CONFIG_MAG_CALIBRATE -#define LIS2MDL_CAL(_s) \ - (&(DOWNCAST(s->drv_data, struct lis2mdl_private_data, data)->cal)) -#endif -#endif - - -#define LIS2MDL_ODR_MIN_VAL 10000 -#define LIS2MDL_ODR_MAX_VAL 50000 -#if (CONFIG_EC_MAX_SENSOR_FREQ_MILLIHZ <= LIS2MDL_ODR_MAX_VAL) -#error "EC too slow for magnetometer" -#endif - -void lis2mdl_normalize(const struct motion_sensor_t *s, - intv3_t v, - uint8_t *data); - -extern const struct accelgyro_drv lis2mdl_drv; - -#endif /* __CROS_EC_MAG_LIS2MDL_H */ - diff --git a/driver/mcdp28x0.c b/driver/mcdp28x0.c deleted file mode 100644 index bf44a6eaf8..0000000000 --- a/driver/mcdp28x0.c +++ /dev/null @@ -1,314 +0,0 @@ -/* Copyright 2014 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. - * - * Megachips DisplayPort to HDMI protocol converter / level shifter driver. - */ - -#include "config.h" -#include "console.h" -#include "common.h" -#include "ec_commands.h" -#include "mcdp28x0.h" -#include "queue.h" -#include "queue_policies.h" -#include "timer.h" -#include "usart-stm32f0.h" -#include "util.h" - -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) - -static uint8_t mcdp_inbuf[MCDP_INBUF_MAX]; - -#undef MCDP_DEBUG - -#ifdef MCDP_DEBUG -static inline void print_buffer(uint8_t *buf, int cnt) -{ - int i; - CPRINTF("buf:"); - for (i = 0; i < cnt; i++) { - if (i && !(i % 4)) - CPRINTF("\n "); - CPRINTF("[%02d]0x%02x ", i, buf[i]); - } - CPRINTF("\n"); -} -#else -static inline void print_buffer(uint8_t *buf, int cnt) {} -#endif - -static struct usart_config const usart_mcdp; - -struct queue const usart_mcdp_rx_queue = QUEUE_DIRECT(MCDP_INBUF_MAX, - uint8_t, - usart_mcdp.producer, - null_consumer); -struct queue const usart_mcdp_tx_queue = QUEUE_DIRECT(MCDP_OUTBUF_MAX, - uint8_t, - null_producer, - usart_mcdp.consumer); - -static struct usart_config const usart_mcdp = USART_CONFIG(CONFIG_MCDP28X0, - usart_rx_interrupt, - usart_tx_interrupt, - 115200, - 0, - usart_mcdp_rx_queue, - usart_mcdp_tx_queue); - -/** - * Compute checksum. - * - * @seed initial value of checksum. - * @msg message bytes to compute checksum on. - * @cnt count of message bytes. - * @return partial checksum. - */ -static uint8_t compute_checksum(uint8_t seed, const uint8_t *msg, int cnt) -{ - int i; - uint8_t chksum = seed; - - for (i = 0; i < cnt; i++) - chksum += msg[i]; - return ~chksum + 1; -} - -/** - * transmit message over serial - * - * Packet consists of: - * msg[0] == length of entire packet - * msg[1] == 1st message byte (typically command) - * msg[cnt+1] == last message byte - * msg[cnt+2] == checksum - * - * @msg message bytes - * @cnt count of message bytes - * @return zero if success, error code otherwise - */ -static int tx_serial(const uint8_t *msg, int cnt) -{ - uint8_t out = cnt + 2; - /* 1st byte (not in msg) is always cnt + 2, so seed chksum with that */ - uint8_t chksum = compute_checksum(cnt + 2, msg, cnt); - - if (queue_add_unit(&usart_mcdp_tx_queue, &out) != 1) - return MCDP_ERROR_TX_CNT; - - if (queue_add_units(&usart_mcdp_tx_queue, msg, cnt) != cnt) - return MCDP_ERROR_TX_BODY; - - print_buffer((uint8_t *)msg, cnt); - - if (queue_add_unit(&usart_mcdp_tx_queue, &chksum) != 1) - return MCDP_ERROR_TX_CHKSUM; - - return MCDP_SUCCESS; -} - -/** - * receive message over serial - * - * While definitive documentation is lacking its believed the following receive - * packet is always true. - * - * Packet consists of: - * msg[0] == length of entire packet - * msg[1] == 1st message byte (typically command) - * msg[cnt+2] == last message byte - * msg[cnt+3] == checksum - * - * @msg pointer to buffer to read message into - * @cnt count of message bytes - * @return zero if success, error code otherwise - */ -static int rx_serial(uint8_t *msg, int cnt) -{ - size_t read; - int retry = 2; - - read = queue_remove_units(&usart_mcdp_rx_queue, msg, cnt); - while ((read < cnt) && retry) { - usleep(100*MSEC); - read += queue_remove_units(&usart_mcdp_rx_queue, msg + read, - cnt - read); - retry--; - } - - print_buffer(msg, cnt); - - /* Some response sizes are dynamic so shrink cnt accordingly. */ - if (cnt > msg[0]) - cnt = msg[0]; - - if (msg[cnt-1] != compute_checksum(0, msg, cnt-1)) - return MCDP_ERROR_CHKSUM; - - if (read != cnt) { - CPRINTF("rx_serial: read bytes %d != %d cnt\n", read, cnt); - return MCDP_ERROR_RX_BYTES; - } - - return MCDP_SUCCESS; -} - -static int rx_serial_ack(void) -{ - int rv = rx_serial(mcdp_inbuf, 3); - if (rv) - return rv; - - if (mcdp_inbuf[1] != MCDP_CMD_ACK) - return MCDP_ERROR_RX_ACK; - - return rv; -} - -void mcdp_enable(void) -{ - usart_init(&usart_mcdp); -} - -void mcdp_disable(void) -{ - usart_shutdown(&usart_mcdp); -} - -int mcdp_get_info(struct mcdp_info *info) -{ - const uint8_t msg[2] = {MCDP_CMD_APPSTEST, 0x28}; - int rv = tx_serial(msg, sizeof(msg)); - - if (rv) - return rv; - - rv = rx_serial_ack(); - if (rv) - return rv; - - /* chksum is unreliable ... don't check */ - rx_serial(mcdp_inbuf, MCDP_RSP_LEN(MCDP_LEN_GETINFO)); - - memcpy(info, &mcdp_inbuf[2], MCDP_LEN_GETINFO); - - return rv; -} - -#ifdef CONFIG_CMD_MCDP -static int mcdp_get_dev_id(char *dev, uint8_t dev_id, int dev_cnt) -{ - uint8_t msg[2]; - int rv; - msg[0] = MCDP_CMD_GETDEVID; - msg[1] = dev_id; - - rv = tx_serial(msg, sizeof(msg)); - if (rv) - return rv; - - rv = rx_serial(mcdp_inbuf, sizeof(mcdp_inbuf)); - if (rv) - return rv; - - memcpy(dev, &mcdp_inbuf[2], mcdp_inbuf[0] - 3); - dev[mcdp_inbuf[0] - 3] = '\0'; - return EC_SUCCESS; -} - -static int mcdp_appstest(uint8_t cmd, int paramc, char **paramv) -{ - uint8_t msg[6]; - char *e; - int i; - int rv = MCDP_SUCCESS; - - /* setup any appstest params */ - msg[0] = MCDP_CMD_APPSTESTPARAM; - for (i = 0; i < paramc; i++) { - uint32_t param = strtoi(paramv[i], &e, 10); - if (*e) - return EC_ERROR_PARAM1; - msg[1] = i + 1; - msg[2] = (param >> 24) & 0xff; - msg[3] = (param >> 16) & 0xff; - msg[4] = (param >> 8) & 0xff; - msg[5] = (param >> 0) & 0xff; - rv = tx_serial(msg, sizeof(msg)); - if (rv) - return rv; - - rv = rx_serial_ack(); - if (rv) - return rv; - } - - msg[0] = MCDP_CMD_APPSTEST; - msg[1] = cmd; - rv = tx_serial(msg, 2); - if (rv) - return rv; - - rv = rx_serial_ack(); - if (rv) - return rv; - - /* magic */ - rx_serial(mcdp_inbuf, sizeof(mcdp_inbuf)); - rx_serial(mcdp_inbuf, sizeof(mcdp_inbuf)); - - return EC_SUCCESS; -} - -int command_mcdp(int argc, char **argv) -{ - int rv = EC_SUCCESS; - char *e; - - if (argc < 2) - return EC_ERROR_PARAM_COUNT; - - mcdp_enable(); - if (!strncasecmp(argv[1], "info", 4)) { - struct mcdp_info info; - rv = mcdp_get_info(&info); - if (!rv) - ccprintf("family:%04x chipid:%04x irom:%d.%d.%d " - "fw:%d.%d.%d\n", - MCDP_FAMILY(info.family), - MCDP_CHIPID(info.chipid), - info.irom.major, info.irom.minor, - info.irom.build, - info.fw.major, info.fw.minor, info.fw.build); - } else if (!strncasecmp(argv[1], "devid", 4)) { - uint8_t dev_id = strtoi(argv[2], &e, 10); - char dev[32]; - if (*e) - return EC_ERROR_PARAM2; - else - rv = mcdp_get_dev_id(dev, dev_id, 32); - if (!rv) - ccprintf("devid[%d] = %s\n", dev_id, dev); - } else if (!strncasecmp(argv[1], "appstest", 4)) { - uint8_t cmd = strtoi(argv[2], &e, 10); - if (*e) - return EC_ERROR_PARAM2; - else - rv = mcdp_appstest(cmd, argc - 3, &argv[3]); - if (!rv) - ccprintf("appstest[%d] completed\n", cmd); - } else { - return EC_ERROR_PARAM1; - } - - mcdp_disable(); - if (rv) - ccprintf("mcdp_error:%d\n", rv); - - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(mcdp, command_mcdp, - "info|devid <id>|appstest <cmd> [<params>]", - "USB PD"); -#endif /* CONFIG_CMD_MCDP */ diff --git a/driver/mcdp28x0.h b/driver/mcdp28x0.h deleted file mode 100644 index 4352a3899e..0000000000 --- a/driver/mcdp28x0.h +++ /dev/null @@ -1,53 +0,0 @@ -/* Copyright 2014 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. - * - * Megachips DisplayPort to HDMI protocol converter / level shifter driver. - */ - -#ifndef __CROS_EC_MCDP28X0_H -#define __CROS_EC_MCDP28X0_H - -#define MCDP_OUTBUF_MAX 16 -#define MCDP_INBUF_MAX 16 - -#define MCDP_CMD_GETINFO 0x40 -#define MCDP_CMD_GETDEVID 0x30 -#define MCDP_CMD_APPSTEST 0x12 -#define MCDP_CMD_APPSTESTPARAM 0x11 -#define MCDP_CMD_ACK 0x0c - -/* packet header (2 bytes: length + cmd) + data + footer (1byte: checksum) */ -#define MCDP_RSP_LEN(len) (len + 3) -#define MCDP_LEN_GETINFO 12 - -/* List of common error codes that can be returned */ -enum mcdp_error_list { - MCDP_SUCCESS = 0, - MCDP_ERROR_TX_CNT, - MCDP_ERROR_TX_BODY, - MCDP_ERROR_TX_CHKSUM, - MCDP_ERROR_CHKSUM, - MCDP_ERROR_RX_BYTES, - MCDP_ERROR_RX_ACK, -}; - -/** - * Enable mcdp driver. - */ -void mcdp_enable(void); - -/** - * Disable mcdp driver. - */ -void mcdp_disable(void); - -/** - * get get information command from mcdp. - * - * @info pointer to mcdp_info structure - * @return zero if success, error code otherwise. - */ -int mcdp_get_info(struct mcdp_info *info); - -#endif diff --git a/driver/pmic_bd99992gw.h b/driver/pmic_bd99992gw.h deleted file mode 100644 index e00ea1d252..0000000000 --- a/driver/pmic_bd99992gw.h +++ /dev/null @@ -1,31 +0,0 @@ -/* Copyright 2018 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. - * - * ROHM BD99992GW PMIC register map. - */ - -#ifndef __CROS_EC_PMIC_BD99992GW_H -#define __CROS_EC_PMIC_BD99992GW_H - -#include "temp_sensor/bd99992gw.h" - -#define BD99992GW_REG_PWRSRCINT 0x04 -#define BD99992GW_REG_RESETIRQ1 0x08 -#define BD99992GW_REG_PBCONFIG 0x14 -#define BD99992GW_REG_PWRSTAT1 0x16 -#define BD99992GW_REG_PWRSTAT2 0x17 -#define BD99992GW_REG_VCCIOCNT 0x30 -#define BD99992GW_REG_V5ADS3CNT 0x31 -#define BD99992GW_REG_V18ACNT 0x34 -#define BD99992GW_REG_V100ACNT 0x37 -#define BD99992GW_REG_V085ACNT 0x38 -#define BD99992GW_REG_VRMODECTRL 0x3b -#define BD99992GW_REG_DISCHGCNT1 0x3c -#define BD99992GW_REG_DISCHGCNT2 0x3d -#define BD99992GW_REG_DISCHGCNT3 0x3e -#define BD99992GW_REG_DISCHGCNT4 0x3f -#define BD99992GW_REG_SDWNCTRL 0x49 -#define BD99992GW_SDWNCTRL_SWDN BIT(0) /* SWDN mask */ - -#endif /* __CROS_EC_PMIC_BD99992GW_H */ diff --git a/driver/pmic_tps650x30.h b/driver/pmic_tps650x30.h deleted file mode 100644 index f03bef5f05..0000000000 --- a/driver/pmic_tps650x30.h +++ /dev/null @@ -1,37 +0,0 @@ -/* Copyright 2017 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. - * - * TI TPS650x30 PMIC register map. - */ - -#ifndef __CROS_EC_PMIC_TPS650X30_H -#define __CROS_EC_PMIC_TPS650X30_H - -/* I2C interface */ -#define TPS650X30_I2C_ADDR1_FLAGS 0x30 -#define TPS650X30_I2C_ADDR2_FLAGS 0x32 -#define TPS650X30_I2C_ADDR3_FLAGS 0x34 - -/* TPS650X30 registers */ -#define TPS650X30_REG_VENDORID 0x00 -#define TPS650X30_REG_PBCONFIG 0x14 -#define TPS650X30_REG_PGMASK1 0x18 -#define TPS650X30_REG_VCCIOCNT 0x30 -#define TPS650X30_REG_V5ADS3CNT 0x31 -#define TPS650X30_REG_V33ADSWCNT 0x32 -#define TPS650X30_REG_V18ACNT 0x34 -#define TPS650X30_REG_V1P2UCNT 0x36 -#define TPS650X30_REG_V100ACNT 0x37 -#define TPS650X30_REG_VRMODECTRL 0x3B -#define TPS650X30_REG_DISCHCNT1 0x3C -#define TPS650X30_REG_DISCHCNT2 0x3D -#define TPS650X30_REG_DISCHCNT3 0x3E -#define TPS650X30_REG_DISCHCNT4 0x3F -#define TPS650X30_REG_PWFAULT_MASK1 0xE5 -#define TPS650X30_REG_PWFAULT_MASK2 0xE6 - -/* TPS650X30 register values */ -#define TPS650X30_VENDOR_ID 0x22 - -#endif /* __CROS_EC_PMIC_TPS650X30_H */ diff --git a/driver/ppc/aoz1380.c b/driver/ppc/aoz1380.c deleted file mode 100644 index 708d488e94..0000000000 --- a/driver/ppc/aoz1380.c +++ /dev/null @@ -1,115 +0,0 @@ -/* Copyright 2019 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. - */ - -/* - * AOZ1380 USB-C Power Path Controller - * - * This is a basic TCPM controlled PPC driver. It could easily be - * renamed and repurposed to be generic, if there are other TCPM - * controlled PPC chips that are similar to the AOZ1380 - */ - -#include "common.h" -#include "console.h" -#include "driver/ppc/aoz1380.h" -#include "hooks.h" -#include "system.h" -#include "tcpm.h" -#include "usb_pd.h" -#include "usb_pd_tcpc.h" -#include "usbc_ppc.h" - -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) - -static uint32_t irq_pending; /* Bitmask of ports signaling an interrupt. */ - -#define AOZ1380_FLAGS_SOURCE_ENABLED BIT(0) -static uint8_t flags[CONFIG_USB_PD_PORT_MAX_COUNT]; - -static int aoz1380_init(int port) -{ - flags[port] = 0; - - return EC_SUCCESS; -} - -static int aoz1380_vbus_sink_enable(int port, int enable) -{ - int rv; - - rv = tcpm_set_snk_ctrl(port, enable); - - return rv; -} - -static int aoz1380_vbus_source_enable(int port, int enable) -{ - int rv; - - rv = tcpm_set_src_ctrl(port, enable); - if (rv) - return rv; - - if (enable) - flags[port] |= AOZ1380_FLAGS_SOURCE_ENABLED; - else - flags[port] &= ~AOZ1380_FLAGS_SOURCE_ENABLED; - - return rv; -} - -static int aoz1380_is_sourcing_vbus(int port) -{ - return flags[port] & AOZ1380_FLAGS_SOURCE_ENABLED; -} - -static int aoz1380_set_vbus_source_current_limit(int port, - enum tcpc_rp_value rp) -{ - return board_aoz1380_set_vbus_source_current_limit(port, rp); -} - -/* - * AOZ1380 Interrupt Handler - * - * This device only has a single over current/temperature interrupt. - * TODO(b/141939343) Determine how to clear the interrupt - * TODO(b/142076004) Test this to verify we shut off vbus current - */ -static void aoz1380_handle_interrupt(int port) -{ - /* - * This is a over current/temperature condition - */ - CPRINTS("C%d: PPC detected Vbus overcurrent/temperature!", port); - pd_handle_overcurrent(port); -} - -static void aoz1380_irq_deferred(void) -{ - int i; - uint32_t pending = atomic_read_clear(&irq_pending); - - for (i = 0; i < board_get_usb_pd_port_count(); i++) - if (BIT(i) & pending) - aoz1380_handle_interrupt(i); -} -DECLARE_DEFERRED(aoz1380_irq_deferred); - -void aoz1380_interrupt(int port) -{ - atomic_or(&irq_pending, BIT(port)); - hook_call_deferred(&aoz1380_irq_deferred_data, 0); -} - -const struct ppc_drv aoz1380_drv = { - .init = &aoz1380_init, - .is_sourcing_vbus = &aoz1380_is_sourcing_vbus, - .vbus_sink_enable = &aoz1380_vbus_sink_enable, - .vbus_source_enable = &aoz1380_vbus_source_enable, - .set_vbus_source_current_limit = - &aoz1380_set_vbus_source_current_limit, -}; diff --git a/driver/ppc/aoz1380.h b/driver/ppc/aoz1380.h deleted file mode 100644 index 94f2b804b7..0000000000 --- a/driver/ppc/aoz1380.h +++ /dev/null @@ -1,44 +0,0 @@ -/* Copyright 2019 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. - */ - -/* - * AOZ1380 USB-C Power Path Controller - * - * This is a basic TCPM controlled PPC driver. It could easily be - * renamed and repurposed to be generic, if there are other TCPM - * controlled PPC chips that are similar to the AOZ1380 - */ - -#ifndef __CROS_EC_AOZ1380_H -#define __CROS_EC_AOZ1380_H - -#include "usb_pd_tcpm.h" - -struct ppc_drv; -extern const struct ppc_drv aoz1380_drv; - -/** - * AOZ1380 Set VBus Source Current Limit. - * - * Using this driver requires a board_aoz1380_set_vbus_source_limit - * function due to the lack of programability of this device and - * requirement for hardware specific code to handle setting this limit. - * - * @param port The Type-C port - * @param rp The Type-C RP value - * @return EC_SUCCESS for success, otherwise error - */ -int board_aoz1380_set_vbus_source_current_limit(int port, - enum tcpc_rp_value rp); - - -/** - * Interrupt Handler for the AOZ1380. - * - * @param port: The Type-C port which triggered the interrupt. - */ -void aoz1380_interrupt(int port); - -#endif /* defined(__CROS_EC_AOZ1380_H) */ diff --git a/driver/ppc/nx20p348x.c b/driver/ppc/nx20p348x.c deleted file mode 100644 index 01c28f52eb..0000000000 --- a/driver/ppc/nx20p348x.c +++ /dev/null @@ -1,473 +0,0 @@ -/* Copyright 2018 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. - */ - -/* NX20P348x USB-C Power Path Controller */ - -#include "common.h" -#include "console.h" -#include "driver/ppc/nx20p348x.h" -#include "gpio.h" -#include "hooks.h" -#include "i2c.h" -#include "system.h" -#include "tcpm.h" -#include "usb_charge.h" -#include "usb_pd_tcpm.h" -#include "usb_pd.h" -#include "usbc_ppc.h" -#include "util.h" - -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) - -static uint32_t irq_pending; /* Bitmask of ports signaling an interrupt. */ - -#define NX20P348X_DB_EXIT_FAIL_THRESHOLD 10 -static int db_exit_fail_count[CONFIG_USB_PD_PORT_MAX_COUNT]; - -#define NX20P348X_FLAGS_SOURCE_ENABLED BIT(0) -static uint8_t flags[CONFIG_USB_PD_PORT_MAX_COUNT]; - -static int read_reg(uint8_t port, int reg, int *regval) -{ - return i2c_read8(ppc_chips[port].i2c_port, - ppc_chips[port].i2c_addr_flags, - reg, - regval); -} - -static int write_reg(uint8_t port, int reg, int regval) -{ - return i2c_write8(ppc_chips[port].i2c_port, - ppc_chips[port].i2c_addr_flags, - reg, - regval); -} - -static int nx20p348x_set_ovp_limit(int port) -{ - int rv; - int reg; - - /* Set VBUS over voltage threshold (OVLO) */ - rv = read_reg(port, NX20P348X_OVLO_THRESHOLD_REG, ®); - if (rv) - return rv; - /* OVLO threshold is 3 bit field */ - reg &= ~NX20P348X_OVLO_THRESHOLD_MASK; - /* Set SNK OVP to 23.0 V */ - reg |= NX20P348X_OVLO_23_0; - rv = write_reg(port, NX20P348X_OVLO_THRESHOLD_REG, reg); - if (rv) - return rv; - - return EC_SUCCESS; -} - -static int nx20p348x_is_sourcing_vbus(int port) -{ - return flags[port] & NX20P348X_FLAGS_SOURCE_ENABLED; -} - -static int nx20p348x_set_vbus_source_current_limit(int port, - enum tcpc_rp_value rp) -{ - int regval; - int status; - - status = read_reg(port, NX20P348X_5V_SRC_OCP_THRESHOLD_REG, ®val); - if (status) - return status; - - regval &= ~NX20P348X_ILIM_MASK; - - /* We need buffer room for all current values. */ - switch (rp) { - case TYPEC_RP_3A0: - regval |= NX20P348X_ILIM_3_200; - break; - - case TYPEC_RP_1A5: - regval |= NX20P348X_ILIM_1_600; - break; - - case TYPEC_RP_USB: - default: - regval |= NX20P348X_ILIM_0_600; - break; - }; - - - return write_reg(port, NX20P348X_5V_SRC_OCP_THRESHOLD_REG, regval); -} - -static int nx20p348x_discharge_vbus(int port, int enable) -{ - int regval; - int status; - - status = read_reg(port, NX20P348X_DEVICE_CONTROL_REG, ®val); - if (status) - return status; - - if (enable) - regval |= NX20P348X_CTRL_VBUSDIS_EN; - else - regval &= ~NX20P348X_CTRL_VBUSDIS_EN; - - status = write_reg(port, NX20P348X_DEVICE_CONTROL_REG, regval); - if (status) { - CPRINTS("Failed to %s vbus discharge", - enable ? "enable" : "disable"); - return status; - } - - return EC_SUCCESS; -} - -static int nx20p348x_vbus_sink_enable(int port, int enable) -{ - int status; - int rv; - int control = enable ? NX20P348X_SWITCH_CONTROL_HVSNK : 0; - - enable = !!enable; - -#if defined(CONFIG_USBC_PPC_NX20P3481) - rv = write_reg(port, NX20P348X_SWITCH_CONTROL_REG, control); -#elif defined(CONFIG_USBC_PPC_NX20P3483) - /* - * We cannot use an EC GPIO for EN_SNK since an EC reset will float the - * GPIO thus browning out the board (without a battery). - */ - rv = tcpm_set_snk_ctrl(port, enable); -#else -#error "Either the NX20P3481 or NX20P3483 must be selected" -#endif - if (rv) - return rv; - - /* - * Read switch status register. The bit definitions for switch control - * and switch status resister are identical, so the control value can be - * compared against the status value. The control switch has a debounce - * (15 msec) before the status will reflect the control command. - */ - msleep(NX20P348X_SWITCH_STATUS_DEBOUNCE_MSEC); - rv = read_reg(port, NX20P348X_SWITCH_STATUS_REG, &status); - if (rv) - return rv; - - return (status & NX20P348X_SWITCH_STATUS_MASK) == control ? - EC_SUCCESS : EC_ERROR_UNKNOWN; -} - -static int nx20p348x_vbus_source_enable(int port, int enable) -{ - int status; - int rv; - uint8_t previous_flags = flags[port]; - int control = enable ? NX20P348X_SWITCH_CONTROL_5VSRC : 0; - - enable = !!enable; - -#if defined(CONFIG_USBC_PPC_NX20P3481) - rv = write_reg(port, NX20P348X_SWITCH_CONTROL_REG, control); -#elif defined(CONFIG_USBC_PPC_NX20P3483) - /* - * For parity's sake, we should not use an EC GPIO for EN_SRC since we - * cannot use it for EN_SNK (for brown out reason listed above). - */ - rv = tcpm_set_src_ctrl(port, enable); -#else -#error "Either the NX20P3481 or NX20P3483 must be selected" -#endif - if (rv) - return rv; - - /* Cache the anticipated Vbus state */ - if (enable) - flags[port] |= NX20P348X_FLAGS_SOURCE_ENABLED; - else - flags[port] &= ~NX20P348X_FLAGS_SOURCE_ENABLED; - - /* - * Read switch status register. The bit definitions for switch control - * and switch status resister are identical, so the control value can be - * compared against the status value. The control switch has a debounce - * (15 msec) before the status will reflect the control command. - */ - msleep(NX20P348X_SWITCH_STATUS_DEBOUNCE_MSEC); - rv = read_reg(port, NX20P348X_SWITCH_STATUS_REG, &status); - if (rv) { - flags[port] = previous_flags; - return rv; - } - - if ((status & NX20P348X_SWITCH_STATUS_MASK) != control) { - flags[port] = previous_flags; - return EC_ERROR_UNKNOWN; - } - - return EC_SUCCESS; -} - -static int nx20p348x_init(int port) -{ - int reg; - int mask; - int mode; - int rv; - enum tcpc_rp_value initial_current_limit; - - /* Mask interrupts for interrupt 2 register */ - mask = ~NX20P348X_INT2_EN_ERR; - rv = write_reg(port, NX20P348X_INTERRUPT2_MASK_REG, mask); - if (rv) - return rv; - - /* Mask interrupts for interrupt 1 register */ - mask = ~(NX20P348X_INT1_OC_5VSRC | NX20P348X_INT1_SC_5VSRC | - NX20P348X_INT1_RCP_5VSRC | NX20P348X_INT1_DBEXIT_ERR); -#if defined(CONFIG_USBC_PPC_NX20P3481) || defined(CONFIG_USBC_PPC_NX20P3483) - /* Unmask Fast Role Swap detect interrupt */ - mask &= ~NX20P348X_INT1_FRS_DET; -#endif - rv = write_reg(port, NX20P348X_INTERRUPT1_MASK_REG, mask); - if (rv) - return rv; - - /* Clear any pending interrupts by reading interrupt registers */ - read_reg(port, NX20P348X_INTERRUPT1_REG, ®); - read_reg(port, NX20P348X_INTERRUPT2_REG, ®); - - /* Get device mode */ - rv = read_reg(port, NX20P348X_DEVICE_STATUS_REG, &mode); - if (rv) - return rv; - mode &= NX20P348X_DEVICE_MODE_MASK; - - /* Check if dead battery mode is active. */ - if (mode == NX20P348X_MODE_DEAD_BATTERY) { - /* - * If in dead battery mode, must enable HV SNK mode prior to - * exiting dead battery mode or VBUS path will get cut off and - * system will lose power. Before DB mode is exited, the device - * mode will not reflect the correct value and therefore the - * return value isn't useful here. - */ - nx20p348x_vbus_sink_enable(port, 1); - - /* Exit dead battery mode. */ - rv = read_reg(port, NX20P348X_DEVICE_CONTROL_REG, ®); - if (rv) - return rv; - reg |= NX20P348X_CTRL_DB_EXIT; - rv = write_reg(port, NX20P348X_DEVICE_CONTROL_REG, reg); - if (rv) - return rv; - } - - /* - * Set VBUS over voltage threshold (OVLO). Note that while the PPC is in - * dead battery mode, OVLO is forced to 6.8V, so this setting must be - * done after dead battery mode is exited. - */ - nx20p348x_set_ovp_limit(port); - - /* Set the Vbus current limit after dead battery mode exit */ -#ifdef CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT - initial_current_limit = CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT; -#else - initial_current_limit = TYPEC_RP_1A5; -#endif - nx20p348x_set_vbus_source_current_limit(port, initial_current_limit); - - return EC_SUCCESS; -} - -static void nx20p348x_handle_interrupt(int port) -{ - int reg; - int control_reg; - - /* - * Read interrupt 1 status register. Note, interrupt register is - * automatically cleared by reading. - */ - read_reg(port, NX20P348X_INTERRUPT1_REG, ®); - - /* Check for DBEXIT error */ - if (reg & NX20P348X_INT1_DBEXIT_ERR) { - int mask_reg; - - /* - * This failure is not expected. If for some reason, this - * keeps happening, then log an error and mask the interrupt to - * prevent interrupt floods. - */ - if (++db_exit_fail_count[port] >= - NX20P348X_DB_EXIT_FAIL_THRESHOLD) { - CPRINTS("Port %d PPC failed to exit DB mode", port); - if (read_reg(port, NX20P348X_INTERRUPT1_MASK_REG, - &mask_reg)) { - mask_reg |= NX20P348X_INT1_DBEXIT_ERR; - write_reg(port, NX20P348X_INTERRUPT1_MASK_REG, - mask_reg); - } - } - read_reg(port, NX20P348X_DEVICE_CONTROL_REG, &control_reg); - reg |= NX20P348X_CTRL_DB_EXIT; - write_reg(port, NX20P348X_DEVICE_CONTROL_REG, control_reg); - /* - * If DB exit mode failed, then the OVP limit setting done in - * the init routine will not be successful. Set the OVP limit - * again here. - */ - nx20p348x_set_ovp_limit(port); - } - - /* Check for 5V OC interrupt */ - if (reg & NX20P348X_INT1_OC_5VSRC) { - CPRINTS("C%d: PPC detected Vbus overcurrent!", port); - pd_handle_overcurrent(port); - } - - /* Check for Vbus reverse current protection */ - if (reg & NX20P348X_INT1_RCP_5VSRC) - CPRINTS("C%d: PPC detected Vbus reverse current!", port); - - /* Check for Vbus short protection */ - if (reg & NX20P348X_INT1_SC_5VSRC) - CPRINTS("C%d: PPC Vbus short detected!", port); - -#ifdef CONFIG_USBC_PPC_NX20P3481 - /* Check for FRS detection */ - if (reg & NX20P348X_INT1_FRS_DET) { - /* - * TODO(b/113069469): Need to check for CC status and verifiy - * that a sink is attached to continue with FRS. If a sink is - * not attached, then this FRS detect is a false detect which is - * triggered when removing an external charger. If FRS was - * detected by the PPC, then it has automatically enabled the - * 5V SRC mode and this must be undone for a proper detach. - */ - /* Check CC status */ - - /* - * False detect, disable SRC mode which was enabled by - * NX20P3481. - */ - CPRINTS("C%d: PPC FRS false detect, disabling SRC mode!", port); - nx20p348x_vbus_source_enable(port, 0); - } -#endif - - /* - * Read interrupt 2 status register. Note, interrupt register is - * automatically cleared by reading. - */ - /* - * TODO (b/75272421): Not sure if any of these interrupts - * will be used. Might want to use EN_ERR which tracks when both - * SNK_EN and SRC_EN are set. However, since for the Analogix TCPC - * these values aren't controlled by the EC directly, not sure what - * action if any can be taken. - */ - read_reg(port, NX20P348X_INTERRUPT2_REG, ®); -} - -static void nx20p348x_irq_deferred(void) -{ - int i; - uint32_t pending = atomic_read_clear(&irq_pending); - - for (i = 0; i < board_get_usb_pd_port_count(); i++) - if (BIT(i) & pending) - nx20p348x_handle_interrupt(i); -} -DECLARE_DEFERRED(nx20p348x_irq_deferred); - -void nx20p348x_interrupt(int port) -{ - atomic_or(&irq_pending, BIT(port)); - hook_call_deferred(&nx20p348x_irq_deferred_data, 0); -} - -#ifdef CONFIG_CMD_PPC_DUMP -static int nx20p348x_dump(int port) -{ - int reg_addr; - int reg; - int rv; - - ccprintf("Port %d NX20P348X registers\n", port); - for (reg_addr = NX20P348X_DEVICE_ID_REG; reg_addr <= - NX20P348X_DEVICE_CONTROL_REG; reg_addr++) { - rv = read_reg(port, reg_addr, ®); - if (rv) { - ccprintf("nx20p: Failed to read register 0x%x\n", - reg_addr); - return rv; - } - ccprintf("[0x%02x]: 0x%02x\n", reg_addr, reg); - - /* Flush every call otherwise buffer may get full */ - cflush(); - } - - return EC_SUCCESS; -} -#endif /* defined(CONFIG_CMD_PPC_DUMP) */ - -/* - * TODO (b/112697473): The NX20P348x PPCs do not support vbus detection or vconn - * generation. However, if a different PPC does support these features and needs - * these config options, then these functions do need to exist. The - * configuration for what each PPC supports should be converted to bits within - * a flags variable that is part of the ppc_config_t struct. - */ -#ifdef CONFIG_USB_PD_VBUS_DETECT_PPC -static int nx20p348x_is_vbus_present(int port) -{ - return EC_ERROR_UNIMPLEMENTED; -} -#endif /* defined(CONFIG_USB_PD_VBUS_DETECT_PPC) */ - -#ifdef CONFIG_USBC_PPC_POLARITY -static int nx20p348x_set_polarity(int port, int polarity) -{ - return EC_ERROR_UNIMPLEMENTED; -} -#endif - -#ifdef CONFIG_USBC_PPC_VCONN -static int nx20p348x_set_vconn(int port, int enable) -{ - return EC_ERROR_UNIMPLEMENTED; -} -#endif - -const struct ppc_drv nx20p348x_drv = { - .init = &nx20p348x_init, - .is_sourcing_vbus = &nx20p348x_is_sourcing_vbus, - .vbus_sink_enable = &nx20p348x_vbus_sink_enable, - .vbus_source_enable = &nx20p348x_vbus_source_enable, -#ifdef CONFIG_CMD_PPC_DUMP - .reg_dump = &nx20p348x_dump, -#endif /* defined(CONFIG_CMD_PPC_DUMP) */ - .set_vbus_source_current_limit = - &nx20p348x_set_vbus_source_current_limit, - .discharge_vbus = &nx20p348x_discharge_vbus, -#ifdef CONFIG_USB_PD_VBUS_DETECT_PPC - .is_vbus_present = &nx20p348x_is_vbus_present, -#endif /* defined(CONFIG_USB_PD_VBUS_DETECT_PPC) */ -#ifdef CONFIG_USBC_PPC_POLARITY - .set_polarity = &nx20p348x_set_polarity, -#endif /* defined(CONFIG_USBC_PPC_POLARITY) */ -#ifdef CONFIG_USBC_PPC_VCONN - .set_vconn = &nx20p348x_set_vconn, -#endif /* defined(CONFIG_USBC_PPC_VCONN) */ -}; diff --git a/driver/ppc/nx20p348x.h b/driver/ppc/nx20p348x.h deleted file mode 100644 index 6aad5c9881..0000000000 --- a/driver/ppc/nx20p348x.h +++ /dev/null @@ -1,131 +0,0 @@ -/* Copyright 2018 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. - */ - -/* NX20P348x Type-C Power Path Controller */ - -#ifndef __CROS_EC_NX20P348X_H -#define __CROS_EC_NX20P348X_H - -#define NX20P3483_ADDR0_FLAGS 0x70 -#define NX20P3483_ADDR1_FLAGS 0x71 -#define NX20P3483_ADDR2_FLAGS 0x72 -#define NX20P3483_ADDR3_FLAGS 0x73 - -#define NX20P3481_ADDR0_FLAGS 0x74 -#define NX20P3481_ADDR1_FLAGS 0x75 -#define NX20P3481_ADDR2_FLAGS 0x76 -#define NX20P3481_ADDR3_FLAGS 0x77 - -/* - * This PPC hard-codes the over voltage protect of Vbus at 6.8V in dead-battery - * mode. If we ever are every going to drop the PD rail, we need to first ensure - * that Vbus is negotiated to below 6.8V otherwise we can lock out Vbus. - */ -#define NX20P348X_SAFE_RESET_VBUS_MV 5000 - -/* NX20P348x register addresses */ -#define NX20P348X_DEVICE_ID_REG 0x00 -#define NX20P348X_DEVICE_STATUS_REG 0x01 -#define NX20P348X_SWITCH_CONTROL_REG 0x02 -#define NX20P348X_SWITCH_STATUS_REG 0x03 -#define NX20P348X_INTERRUPT1_REG 0x04 -#define NX20P348X_INTERRUPT2_REG 0x05 -#define NX20P348X_INTERRUPT1_MASK_REG 0x06 -#define NX20P348X_INTERRUPT2_MASK_REG 0x07 -#define NX20P348X_OVLO_THRESHOLD_REG 0x08 -#define NX20P348X_HV_SRC_OCP_THRESHOLD_REG 0x09 -#define NX20P348X_5V_SRC_OCP_THRESHOLD_REG 0x0A -#define NX20P348X_DEVICE_CONTROL_REG 0x0B - -/* Device Control Register */ -#define NX20P348X_CTRL_FRS_AT BIT(3) -#define NX20P348X_CTRL_DB_EXIT BIT(2) -#define NX20P348X_CTRL_VBUSDIS_EN BIT(1) -#define NX20P348X_CTRL_LDO_SD BIT(0) - -/* Device Status Modes */ -#define NX20P348X_DEVICE_MODE_MASK 0x7 -#define NX20P348X_MODE_DEAD_BATTERY 0 -/* After dead battery, mode values are different between 3481 and 3483 */ -#define NX20P3481_MODE_NORMAL 1 -#define NX20P3481_MODE_FRS 2 -#define NX20P3481_MODE_STANDBY 3 - -#define NX20P3483_MODE_HV_SNK 1 -#define NX20P3483_MODE_5V_SRC 2 -#define NX20P3483_MODE_HV_SRC 3 -#define NX20P3483_MODE_STANDBY 4 - -/* Switch Control Register */ -#define NX20P348X_SWITCH_CONTROL_HVSNK BIT(0) -#define NX20P348X_SWITCH_CONTROL_HVSRC BIT(1) -#define NX20P348X_SWITCH_CONTROL_5VSRC BIT(2) - -/* Switch Status Register */ -#define NX20P348X_HVSNK_STS BIT(0) -#define NX20P348X_HVSRC_STS BIT(1) -#define NX20P348X_5VSRC_STS BIT(2) -#define NX20P348X_SWITCH_STATUS_DEBOUNCE_MSEC 25 -#define NX20P348X_SWITCH_STATUS_MASK 0x7 - -/* Internal 5V VBUS Switch Current Limit Settings (min) */ -#define NX20P348X_ILIM_MASK 0xF -#define NX20P348X_ILIM_0_400 0 -#define NX20P348X_ILIM_0_600 1 -#define NX20P348X_ILIM_0_800 2 -#define NX20P348X_ILIM_1_000 3 -#define NX20P348X_ILIM_1_200 4 -#define NX20P348X_ILIM_1_400 5 -#define NX20P348X_ILIM_1_600 6 -#define NX20P348X_ILIM_1_800 7 -#define NX20P348X_ILIM_2_000 8 -#define NX20P348X_ILIM_2_200 9 -#define NX20P348X_ILIM_2_400 10 -#define NX20P348X_ILIM_2_600 11 -#define NX20P348X_ILIM_2_800 12 -#define NX20P348X_ILIM_3_000 13 -#define NX20P348X_ILIM_3_200 14 -#define NX20P348X_ILIM_3_400 15 - -/* HV VBUS over voltage threshold settings V_mV*/ -#define NX20P348X_OVLO_THRESHOLD_MASK 0x7 -#define NX20P348X_OVLO_06_0 0 -#define NX20P348X_OVLO_06_8 1 -#define NX20P348X_OVLO_10_0 2 -#define NX20P348X_OVLO_11_5 3 -#define NX20P348X_OVLO_14_0 4 -#define NX20P348X_OVLO_17_0 5 -#define NX20P348X_OVLO_23_0 6 - -/* Interrupt 1 Register Bits */ -#define NX20P348X_INT1_DBEXIT_ERR BIT(7) -#define NX20P348X_INT1_FRS_DET BIT(6) -#define NX20P348X_INT1_OV_5VSRC BIT(4) -#define NX20P348X_INT1_RCP_5VSRC BIT(3) -#define NX20P348X_INT1_SC_5VSRC BIT(2) -#define NX20P348X_INT1_OC_5VSRC BIT(1) -#define NX20P348X_INT1_OTP BIT(0) - -/* Interrupt 2 Register Bits */ -#define NX20P348X_INT2_EN_ERR BIT(7) -#define NX20P348X_INT2_RCP_HVSNK BIT(6) -#define NX20P348X_INT2_SC_HVSNK BIT(5) -#define NX20P348X_INT2_OV_HVSNK BIT(4) -#define NX20P348X_INT2_RCP_HVSRC BIT(3) -#define NX20P348X_INT2_SC_HVSRC BIT(2) -#define NX20P348X_INT2_OC_HVSRC BIT(1) -#define NX20P348X_INT2_OV_HVSRC BIT(0) - -struct ppc_drv; -extern const struct ppc_drv nx20p348x_drv; - -/** - * Interrupt Handler for the NX20P348x. - * - * @param port: The Type-C port which triggered the interrupt. - */ -void nx20p348x_interrupt(int port); - -#endif /* defined(__CROS_EC_NX20P348X_H) */ diff --git a/driver/ppc/sn5s330.c b/driver/ppc/sn5s330.c deleted file mode 100644 index cdc355a8ae..0000000000 --- a/driver/ppc/sn5s330.c +++ /dev/null @@ -1,788 +0,0 @@ -/* Copyright 2017 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. - */ - -/* TI SN5S330 USB-C Power Path Controller */ - -/* - * PP1 : Sourcing power path. - * PP2 : Sinking power path. - */ - -#include "common.h" -#include "console.h" -#include "driver/ppc/sn5s330.h" -#include "hooks.h" -#include "i2c.h" -#include "system.h" -#include "timer.h" -#include "usb_charge.h" -#include "usb_pd_tcpm.h" -#include "usb_pd.h" -#include "usbc_ppc.h" -#include "util.h" - -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) - -static uint32_t irq_pending; /* Bitmask of ports signaling an interrupt. */ -static int source_enabled[CONFIG_USB_PD_PORT_MAX_COUNT]; - -static int read_reg(uint8_t port, int reg, int *regval) -{ - return i2c_read8(ppc_chips[port].i2c_port, - ppc_chips[port].i2c_addr_flags, - reg, - regval); -} - -static int write_reg(uint8_t port, int reg, int regval) -{ - return i2c_write8(ppc_chips[port].i2c_port, - ppc_chips[port].i2c_addr_flags, - reg, - regval); -} - -static int set_flags(const int port, const int addr, const int flags_to_set) -{ - int val, rv; - - rv = read_reg(port, addr, &val); - if (rv) - return rv; - - val |= flags_to_set; - - return write_reg(port, addr, val); -} - - -static int clr_flags(const int port, const int addr, const int flags_to_clear) -{ - int val, rv; - - rv = read_reg(port, addr, &val); - if (rv) - return rv; - - val &= ~flags_to_clear; - - return write_reg(port, addr, val); -} - -#ifdef CONFIG_CMD_PPC_DUMP -static int sn5s330_dump(int port) -{ - int i; - int data; - const int i2c_port = ppc_chips[port].i2c_port; - const uint16_t i2c_addr_flags = ppc_chips[port].i2c_addr_flags; - - /* Flush after every set otherwise console buffer may get full. */ - - for (i = SN5S330_FUNC_SET1; i <= SN5S330_FUNC_SET12; i++) { - i2c_read8(i2c_port, i2c_addr_flags, i, &data); - ccprintf("FUNC_SET%d [%02Xh] = 0x%02x\n", - i - SN5S330_FUNC_SET1 + 1, - i, - data); - } - - cflush(); - - for (i = SN5S330_INT_STATUS_REG1; i <= SN5S330_INT_STATUS_REG4; i++) { - i2c_read8(i2c_port, i2c_addr_flags, i, &data); - ccprintf("INT_STATUS_REG%d [%02Xh] = 0x%02x\n", - i - SN5S330_INT_STATUS_REG1 + 1, - i, - data); - } - - cflush(); - - for (i = SN5S330_INT_TRIP_RISE_REG1; i <= SN5S330_INT_TRIP_RISE_REG3; - i++) { - i2c_read8(i2c_port, i2c_addr_flags, i, &data); - ccprintf("INT_TRIP_RISE_REG%d [%02Xh] = 0x%02x\n", - i - SN5S330_INT_TRIP_RISE_REG1 + 1, - i, - data); - } - - cflush(); - - for (i = SN5S330_INT_TRIP_FALL_REG1; i <= SN5S330_INT_TRIP_FALL_REG3; - i++) { - i2c_read8(i2c_port, i2c_addr_flags, i, &data); - ccprintf("INT_TRIP_FALL_REG%d [%02Xh] = 0x%02x\n", - i - SN5S330_INT_TRIP_FALL_REG1 + 1, - i, - data); - } - - cflush(); - - for (i = SN5S330_INT_MASK_RISE_REG1; i <= SN5S330_INT_MASK_RISE_REG3; - i++) { - i2c_read8(i2c_port, i2c_addr_flags, i, &data); - ccprintf("INT_MASK_RISE_REG%d [%02Xh] = 0x%02x\n", - i - SN5S330_INT_MASK_RISE_REG1 + 1, - i, - data); - } - - cflush(); - - for (i = SN5S330_INT_MASK_FALL_REG1; i <= SN5S330_INT_MASK_FALL_REG3; - i++) { - i2c_read8(i2c_port, i2c_addr_flags, i, &data); - ccprintf("INT_MASK_FALL_REG%d [%02Xh] = 0x%02x\n", - i - SN5S330_INT_MASK_FALL_REG1 + 1, - i, - data); - } - - cflush(); - - return EC_SUCCESS; -} -#endif /* defined(CONFIG_CMD_PPC_DUMP) */ - -static int sn5s330_pp_fet_enable(uint8_t port, enum sn5s330_pp_idx pp, - int enable) -{ - int status; - int pp_bit; - - if (pp == SN5S330_PP1) - pp_bit = SN5S330_PP1_EN; - else if (pp == SN5S330_PP2) - pp_bit = SN5S330_PP2_EN; - else - return EC_ERROR_INVAL; - - status = enable ? set_flags(port, SN5S330_FUNC_SET3, pp_bit) - : clr_flags(port, SN5S330_FUNC_SET3, pp_bit); - - if (status) { - CPRINTS("ppc p%d: Failed to set FUNC_SET3!", port); - return status; - } - - if (pp == SN5S330_PP1) - source_enabled[port] = enable; - - return EC_SUCCESS; -} - -static int sn5s330_init(int port) -{ - int regval; - int status; - int retries; - int reg; - const int i2c_port = ppc_chips[port].i2c_port; - const uint16_t i2c_addr_flags = ppc_chips[port].i2c_addr_flags; - -#ifdef CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT - /* Set the sourcing current limit value. */ - switch (CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT) { - case TYPEC_RP_3A0: - /* Set current limit to ~3A. */ - regval = SN5S330_ILIM_3_06; - break; - - case TYPEC_RP_1A5: - default: - /* Set current limit to ~1.5A. */ - regval = SN5S330_ILIM_1_62; - break; - } -#else /* !defined(CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT) */ - /* Default SRC current limit to ~1.5A. */ - regval = SN5S330_ILIM_1_62; -#endif /* defined(CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT) */ - - /* - * It seems that sometimes setting the FUNC_SET1 register fails - * initially. Therefore, we'll retry a couple of times. - */ - retries = 0; - do { - status = i2c_write8(i2c_port, i2c_addr_flags, - SN5S330_FUNC_SET1, regval); - if (status) { - CPRINTS("ppc p%d: Failed to set FUNC_SET1! Retrying..", - port); - retries++; - msleep(1); - } else { - break; - } - } while (retries < 10); - - /* Set Vbus OVP threshold to ~22.325V. */ - regval = 0x37; - status = i2c_write8(i2c_port, i2c_addr_flags, - SN5S330_FUNC_SET5, regval); - if (status) { - CPRINTS("ppc p%d: Failed to set FUNC_SET5!", port); - return status; - } - - /* Set Vbus UVP threshold to ~2.75V. */ - status = i2c_read8(i2c_port, i2c_addr_flags, - SN5S330_FUNC_SET6, ®val); - if (status) { - CPRINTS("ppc p%d: Failed to read FUNC_SET6!", port); - return status; - } - regval &= ~0x3F; - regval |= 1; - status = i2c_write8(i2c_port, i2c_addr_flags, - SN5S330_FUNC_SET6, regval); - if (status) { - CPRINTS("ppc p%d: Failed to write FUNC_SET6!", port); - return status; - } - - /* Enable SBU Fets and set PP2 current limit to ~3A. */ - regval = SN5S330_SBU_EN | 0x8; - status = i2c_write8(i2c_port, i2c_addr_flags, - SN5S330_FUNC_SET2, regval); - if (status) { - CPRINTS("ppc p%d: Failed to set FUNC_SET2!", port); - return status; - } - - /* - * Indicate we are using PP2 configuration 2 and enable OVP comparator - * for CC lines. - * - * Also, turn off under-voltage protection for incoming Vbus as it would - * prevent us from enabling SNK path before we hibernate the ec. We - * need to enable the SNK path so USB power will assert ACOK and wake - * the EC up went inserting USB power. We always turn off under-voltage - * protection because the battery charger will boost the voltage up - * to the needed battery voltage either way (and it will have its own - * low voltage protection). - */ - regval = SN5S330_OVP_EN_CC | SN5S330_PP2_CONFIG | SN5S330_CONFIG_UVP; - status = i2c_write8(i2c_port, i2c_addr_flags, - SN5S330_FUNC_SET9, regval); - if (status) { - CPRINTS("ppc p%d: Failed to set FUNC_SET9!", port); - return status; - } - - /* Set analog current limit delay to 200 us for both PP1 & PP2. */ - regval = (PPX_ILIM_DEGLITCH_0_US_200 << 3) | PPX_ILIM_DEGLITCH_0_US_200; - status = i2c_write8(i2c_port, i2c_addr_flags, - SN5S330_FUNC_SET11, regval); - if (status) { - CPRINTS("ppc p%d: Failed to set FUNC_SET11", port); - return status; - } - -#ifdef CONFIG_USBC_PPC_VCONN - /* - * Set the deglitch timeout on the Vconn current limit to 640us. This - * improves compatibility with some USB C -> HDMI devices versus the - * reset default (20 us). - */ - regval = 0; - status = i2c_read8(i2c_port, i2c_addr_flags, - SN5S330_FUNC_SET8, ®val); - if (status) { - CPRINTS("ppc p%d: Failed to read FUNC_SET8!", port); - return status; - } - regval &= ~SN5S330_VCONN_DEGLITCH_MASK; - regval |= SN5S330_VCONN_DEGLITCH_640_US; - status = i2c_write8(i2c_port, i2c_addr_flags, - SN5S330_FUNC_SET8, regval); - if (status) { - CPRINTS("ppc p%d: Failed to set FUNC_SET8!", port); - return status; - } -#endif /* CONFIG_USBC_PPC_VCONN */ - - /* - * Turn off dead battery resistors, turn on CC FETs, and set the higher - * of the two VCONN current limits (min 0.6A). Many VCONN accessories - * trip the default current limit of min 0.35A. - */ - status = set_flags(port, SN5S330_FUNC_SET4, - SN5S330_CC_EN | SN5S330_VCONN_ILIM_SEL); - if (status) { - CPRINTS("ppc p%d: Failed to set FUNC_SET4!", port); - return status; - } - - /* Set ideal diode mode for both PP1 and PP2. */ - status = set_flags(port, SN5S330_FUNC_SET3, - SN5S330_SET_RCP_MODE_PP1 | SN5S330_SET_RCP_MODE_PP2); - if (status) { - CPRINTS("ppc p%d: Failed to set FUNC_SET3!", port); - return status; - } - - /* Turn off PP1 FET. */ - status = sn5s330_pp_fet_enable(port, SN5S330_PP1, 0); - if (status) { - CPRINTS("ppc p%d: Failed to turn off PP1 FET!", port); - } - - /* - * Unmask the VCONN ILIM interrupt so we can print VCONN overcurrent - * events. - */ - clr_flags(port, SN5S330_INT_MASK_RISE_REG2, SN5S330_VCONN_ILIM); - - /* - * Unmask the CC1/CC2 OVP interrupt so we can print CC1/CC2 OVP events - */ - clr_flags(port, SN5S330_INT_MASK_RISE_REG2, SN5S330_CC1_CON); - clr_flags(port, SN5S330_INT_MASK_RISE_REG2, SN5S330_CC2_CON); - - /* - * Don't proceed with the rest of initialization if we're sysjumping. - * We would have already done this before. - */ - if (system_jumped_to_this_image()) - return EC_SUCCESS; - - /* - * Clear the digital reset bit, and mask off and clear vSafe0V - * interrupts. Leave the dead battery mode bit unchanged since it - * is checked below. - */ - regval = SN5S330_DIG_RES | SN5S330_VSAFE0V_MASK; - status = i2c_write8(i2c_port, i2c_addr_flags, - SN5S330_INT_STATUS_REG4, regval); - if (status) { - CPRINTS("ppc p%d: Failed to write INT_STATUS_REG4!", port); - return status; - } - - /* - * Before turning on the PP2 FET, let's mask off all interrupts except - * for the PP1 overcurrent condition and then clear all pending - * interrupts. If PPC is being used to detect VBUS, then also enable - * interrupts for VBUS presence. - * - * TODO(aaboagye): Unmask fast-role swap events once fast-role swap is - * implemented in the PD stack. - */ - - regval = ~SN5S330_ILIM_PP1_MASK; - status = i2c_write8(i2c_port, i2c_addr_flags, - SN5S330_INT_MASK_RISE_REG1, regval); - if (status) { - CPRINTS("ppc p%d: Failed to write INT_MASK_RISE1!", port); - return status; - } - - status = i2c_write8(i2c_port, i2c_addr_flags, - SN5S330_INT_MASK_FALL_REG1, regval); - if (status) { - CPRINTS("ppc p%d: Failed to write INT_MASK_FALL1!", port); - return status; - } - - /* Now mask all the other interrupts. */ - status = i2c_write8(i2c_port, i2c_addr_flags, - SN5S330_INT_MASK_RISE_REG2, 0xFF); - if (status) { - CPRINTS("ppc p%d: Failed to write INT_MASK_RISE2!", port); - return status; - } - - status = i2c_write8(i2c_port, i2c_addr_flags, - SN5S330_INT_MASK_FALL_REG2, 0xFF); - if (status) { - CPRINTS("ppc p%d: Failed to write INT_MASK_FALL2!", port); - return status; - } - - /* - * Unmask the CC1/CC2 OVP interrupt so we can print CC1/CC2 OVP events - */ - clr_flags(port, SN5S330_INT_MASK_RISE_REG2, SN5S330_CC1_CON); - clr_flags(port, SN5S330_INT_MASK_RISE_REG2, SN5S330_CC2_CON); - -#if defined(CONFIG_USB_PD_VBUS_DETECT_PPC) && defined(CONFIG_USB_CHARGER) - /* If PPC is being used to detect VBUS, enable VBUS interrupts. */ - regval = ~SN5S330_VBUS_GOOD_MASK; -#else - regval = 0xFF; -#endif /* CONFIG_USB_PD_VBUS_DETECT_PPC && CONFIG_USB_CHARGER */ - - status = i2c_write8(i2c_port, i2c_addr_flags, - SN5S330_INT_MASK_RISE_REG3, regval); - if (status) { - CPRINTS("ppc p%d: Failed to write INT_MASK_RISE3!", port); - return status; - } - - status = i2c_write8(i2c_port, i2c_addr_flags, - SN5S330_INT_MASK_FALL_REG3, regval); - if (status) { - CPRINTS("ppc p%d: Failed to write INT_MASK_FALL3!", port); - return status; - } - - /* Now clear any pending interrupts. */ - for (reg = SN5S330_INT_TRIP_RISE_REG1; - reg <= SN5S330_INT_TRIP_FALL_REG3; - reg++) { - status = i2c_write8(i2c_port, i2c_addr_flags, - reg, 0xFF); - if (status) { - CPRINTS("ppc p%d: Failed to write reg 0x%2x!", - port, reg); - return status; - } - } - - - /* - * For PP2, check to see if we booted in dead battery mode. If we - * booted in dead battery mode, the PP2 FET will already be enabled. - */ - status = i2c_read8(i2c_port, i2c_addr_flags, - SN5S330_INT_STATUS_REG4, ®val); - if (status) { - CPRINTS("ppc p%d: Failed to read INT_STATUS_REG4!", port); - return status; - } - - if (regval & SN5S330_DB_BOOT) { - /* - * Clear the bit by writing 1 and keep vSafe0V_MASK - * unchanged. - */ - i2c_write8(i2c_port, i2c_addr_flags, - SN5S330_INT_STATUS_REG4, regval); - - /* Turn on PP2 FET. */ - status = sn5s330_pp_fet_enable(port, SN5S330_PP2, 1); - if (status) { - CPRINTS("ppc p%d: Failed to turn on PP2 FET!", port); - return status; - } - } - - return EC_SUCCESS; -} - -#ifdef CONFIG_USB_PD_VBUS_DETECT_PPC -static int sn5s330_is_vbus_present(int port) -{ - int regval; - int rv; - - rv = read_reg(port, SN5S330_INT_STATUS_REG3, ®val); - if (rv) { - CPRINTS("ppc p%d: VBUS present error (%d)", port, rv); - return 0; - } - - return !!(regval & SN5S330_VBUS_GOOD); -} -#endif /* defined(CONFIG_USB_PD_VBUS_DETECT_PPC) */ - -static int sn5s330_is_sourcing_vbus(int port) -{ - return source_enabled[port]; -} - -#ifdef CONFIG_USBC_PPC_POLARITY -static int sn5s330_set_polarity(int port, int polarity) -{ - if (polarity) - /* CC2 active. */ - return set_flags(port, SN5S330_FUNC_SET4, SN5S330_CC_POLARITY); - else - /* CC1 active. */ - return clr_flags(port, SN5S330_FUNC_SET4, SN5S330_CC_POLARITY); -} -#endif - -static int sn5s330_set_vbus_source_current_limit(int port, - enum tcpc_rp_value rp) -{ - int regval; - int status; - - status = read_reg(port, SN5S330_FUNC_SET1, ®val); - if (status) - return status; - - /* - * Note that we chose the lowest current limit setting that is just - * above indicated Rp value. This is because these are minimum values - * and we must be able to provide the current that we advertise. - */ - regval &= ~0x1F; /* The current limit settings are 4:0. */ - switch (rp) { - case TYPEC_RP_3A0: - regval |= SN5S330_ILIM_3_06; - break; - - case TYPEC_RP_1A5: - regval |= SN5S330_ILIM_1_62; - break; - - case TYPEC_RP_USB: - default: - regval |= SN5S330_ILIM_0_63; - break; - }; - - status = write_reg(port, SN5S330_FUNC_SET1, regval); - - return status; -} - -static int sn5s330_discharge_vbus(int port, int enable) -{ - int status = enable ? set_flags(port, SN5S330_FUNC_SET3, - SN5S330_VBUS_DISCH_EN) - : clr_flags(port, SN5S330_FUNC_SET3, - SN5S330_VBUS_DISCH_EN); - - if (status) { - CPRINTS("ppc p%d: Failed to %s vbus discharge", - port, enable ? "enable" : "disable"); - return status; - } - - return EC_SUCCESS; -} - -static int sn5s330_enter_low_power_mode(int port) -{ - int rv; - - /* Turn off both SRC and SNK FETs */ - rv = clr_flags(port, SN5S330_FUNC_SET3, - SN5S330_PP1_EN | SN5S330_PP2_EN); - - if (rv) { - CPRINTS("ppc p%d: Could not disable both FETS (%d)", port, rv); - return rv; - } - - /* Turn off Vconn power */ - rv = clr_flags(port, SN5S330_FUNC_SET4, SN5S330_VCONN_EN); - - if (rv) { - CPRINTS("ppc p%d: Could not disable Vconn (%d)", port, rv); - return rv; - } - - /* Turn off SBU path */ - rv = clr_flags(port, SN5S330_FUNC_SET2, SN5S330_SBU_EN); - - if (rv) { - CPRINTS("ppc p%d: Could not disable SBU path (%d)", port, rv); - return rv; - } - - /* - * Turn off the Over Voltage Protection circuits. Needs to happen after - * FETs are disabled, otherwise OVP can automatically turned back on. - * Since FETs are off, any over voltage does not make it to the board - * side of the PPC. - */ - rv = clr_flags(port, SN5S330_FUNC_SET9, - SN5S330_FORCE_OVP_EN_SBU | SN5S330_FORCE_ON_VBUS_OVP | - SN5S330_FORCE_ON_VBUS_UVP); - - if (rv) { - CPRINTS("ppc p%d: Could not disable OVP circuit (%d)", port, - rv); - return rv; - } - - return EC_SUCCESS; -} - -#ifdef CONFIG_USBC_PPC_VCONN -static int sn5s330_set_vconn(int port, int enable) -{ - int regval; - int status; - - status = read_reg(port, SN5S330_FUNC_SET4, ®val); - if (status) - return status; - - if (enable) - regval |= SN5S330_VCONN_EN; - else - regval &= ~SN5S330_VCONN_EN; - - return write_reg(port, SN5S330_FUNC_SET4, regval); -} -#endif - -static int sn5s330_vbus_sink_enable(int port, int enable) -{ - return sn5s330_pp_fet_enable(port, SN5S330_PP2, !!enable); -} - -static int sn5s330_vbus_source_enable(int port, int enable) -{ - return sn5s330_pp_fet_enable(port, SN5S330_PP1, !!enable); -} - -#ifdef CONFIG_USBC_PPC_SBU -static int sn5s330_set_sbu(int port, int enable) -{ - int rv; - - if (enable) - rv = set_flags(port, SN5S330_FUNC_SET2, SN5S330_SBU_EN); - else - rv = clr_flags(port, SN5S330_FUNC_SET2, SN5S330_SBU_EN); - - return rv; -} -#endif /* CONFIG_USBC_PPC_SBU */ - -static void sn5s330_handle_interrupt(int port) -{ - int attempt = 0; - - /* - * SN5S330's /INT pin is level, so process interrupts until it - * deasserts if the chip has a dedicated interrupt pin. - */ -#ifdef CONFIG_USBC_PPC_DEDICATED_INT - while (ppc_get_alert_status(port)) -#endif - { - int rise = 0; - int fall = 0; - int regval = 0; - int retries = 0; - - attempt++; - - if (attempt > 1) - CPRINTS("ppc p%d: Could not clear interrupts on first " - "try, retrying", port); - - /* - * The only interrupts that should be enabled are the PP1 - * overcurrent condition, and for VBUS_GOOD if PPC is being - * used to detect VBUS. - */ - read_reg(port, SN5S330_INT_TRIP_RISE_REG1, &rise); - read_reg(port, SN5S330_INT_TRIP_FALL_REG1, &fall); - - /* Notify the system about the overcurrent event. */ - if (rise & SN5S330_ILIM_PP1_MASK) - pd_handle_overcurrent(port); - - /* Clear the interrupt sources. */ - write_reg(port, SN5S330_INT_TRIP_RISE_REG1, rise); - write_reg(port, SN5S330_INT_TRIP_FALL_REG1, fall); - -#if defined(CONFIG_USB_PD_VBUS_DETECT_PPC) && defined(CONFIG_USB_CHARGER) - read_reg(port, SN5S330_INT_TRIP_RISE_REG3, &rise); - read_reg(port, SN5S330_INT_TRIP_FALL_REG3, &fall); - - /* Inform other modules about VBUS level */ - if (rise & SN5S330_VBUS_GOOD_MASK - || fall & SN5S330_VBUS_GOOD_MASK) - usb_charger_vbus_change(port, - sn5s330_is_vbus_present(port)); - - /* Clear the interrupt sources. */ - write_reg(port, SN5S330_INT_TRIP_RISE_REG3, rise); - write_reg(port, SN5S330_INT_TRIP_FALL_REG3, fall); -#endif /* CONFIG_USB_PD_VBUS_DETECT_PPC && CONFIG_USB_CHARGER */ - - /* - * VCONN may be latched off due to an overcurrent. Indicate - * when the VCONN overcurrent happens. - */ - read_reg(port, SN5S330_INT_TRIP_RISE_REG2, &rise); - read_reg(port, SN5S330_INT_TRIP_FALL_REG2, &fall); - - if (rise & SN5S330_VCONN_ILIM) - CPRINTS("ppc p%d: VCONN OC!", port); - - if (rise & SN5S330_CC1_CON || rise & SN5S330_CC2_CON) { - CPRINTS("ppc p%d: CC OVP!", port); - retries = 0; - do { - read_reg(port, SN5S330_INT_STATUS_REG3, - ®val); - if (regval & SN5S330_VBUS_GOOD) { - sn5s330_set_sbu(port, 1); - sn5s330_pp_fet_enable(port, - SN5S330_PP2, 1); - break; - } - retries++; - msleep(1); - } while (retries < 10); - - if (retries == 10) - CPRINTS("ppc p%d: Fail to release cc OVP." - , port); - } - - /* Clear the interrupt sources. */ - write_reg(port, SN5S330_INT_TRIP_RISE_REG2, rise); - write_reg(port, SN5S330_INT_TRIP_FALL_REG2, fall); - } -} - -static void sn5s330_irq_deferred(void) -{ - int i; - uint32_t pending = atomic_read_clear(&irq_pending); - - for (i = 0; i < board_get_usb_pd_port_count(); i++) - if (BIT(i) & pending) - sn5s330_handle_interrupt(i); -} -DECLARE_DEFERRED(sn5s330_irq_deferred); - -void sn5s330_interrupt(int port) -{ - atomic_or(&irq_pending, BIT(port)); - hook_call_deferred(&sn5s330_irq_deferred_data, 0); -} - -const struct ppc_drv sn5s330_drv = { - .init = &sn5s330_init, - .is_sourcing_vbus = &sn5s330_is_sourcing_vbus, - .vbus_sink_enable = &sn5s330_vbus_sink_enable, - .vbus_source_enable = &sn5s330_vbus_source_enable, - .set_vbus_source_current_limit = &sn5s330_set_vbus_source_current_limit, - .discharge_vbus = &sn5s330_discharge_vbus, - .enter_low_power_mode = &sn5s330_enter_low_power_mode, -#ifdef CONFIG_CMD_PPC_DUMP - .reg_dump = &sn5s330_dump, -#endif -#ifdef CONFIG_USB_PD_VBUS_DETECT_PPC - .is_vbus_present = &sn5s330_is_vbus_present, -#endif -#ifdef CONFIG_USBC_PPC_POLARITY - .set_polarity = &sn5s330_set_polarity, -#endif -#ifdef CONFIG_USBC_PPC_SBU - .set_sbu = &sn5s330_set_sbu, -#endif /* defined(CONFIG_USBC_PPC_SBU) */ -#ifdef CONFIG_USBC_PPC_VCONN - .set_vconn = &sn5s330_set_vconn, -#endif -}; diff --git a/driver/ppc/sn5s330.h b/driver/ppc/sn5s330.h deleted file mode 100644 index 94d0ab0f1e..0000000000 --- a/driver/ppc/sn5s330.h +++ /dev/null @@ -1,177 +0,0 @@ -/* Copyright 2017 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. - */ - -/* TI SN5S330 Type-C Power Path Controller */ - -#ifndef __CROS_EC_SN5S330_H -#define __CROS_EC_SN5S330_H - -#include "common.h" - -struct sn5s330_config { - uint8_t i2c_port; - uint8_t i2c_addr_flags; -}; - -extern const struct sn5s330_config sn5s330_chips[]; -extern const unsigned int sn5s330_cnt; - -/* Power Path Indices */ -enum sn5s330_pp_idx { - SN5S330_PP1, - SN5S330_PP2, - SN5S330_PP_COUNT, -}; - -#define SN5S330_ADDR0_FLAGS 0x40 -#define SN5S330_ADDR1_FLAGS 0x41 -#define SN5S330_ADDR2_FLAGS 0x42 -#define SN5S330_ADDR3_FLAGS 0x43 - -#define SN5S330_FUNC_SET1 0x50 -#define SN5S330_FUNC_SET2 0x51 -#define SN5S330_FUNC_SET3 0x52 -#define SN5S330_FUNC_SET4 0x53 -#define SN5S330_FUNC_SET5 0x54 -#define SN5S330_FUNC_SET6 0x55 -#define SN5S330_FUNC_SET7 0x56 -#define SN5S330_FUNC_SET8 0x57 -#define SN5S330_FUNC_SET9 0x58 -#define SN5S330_FUNC_SET10 0x59 -#define SN5S330_FUNC_SET11 0x5A -#define SN5S330_FUNC_SET12 0x5B - -#define SN5S330_INT_STATUS_REG1 0x2F -#define SN5S330_INT_STATUS_REG2 0x30 -#define SN5S330_INT_STATUS_REG3 0x31 -#define SN5S330_INT_STATUS_REG4 0x32 - -#define SN5S330_INT_TRIP_RISE_REG1 0x20 -#define SN5S330_INT_TRIP_RISE_REG2 0x21 -#define SN5S330_INT_TRIP_RISE_REG3 0x22 -#define SN5S330_INT_TRIP_FALL_REG1 0x23 -#define SN5S330_INT_TRIP_FALL_REG2 0x24 -#define SN5S330_INT_TRIP_FALL_REG3 0x25 - -#define SN5S330_INT_MASK_RISE_REG1 0x26 -#define SN5S330_INT_MASK_RISE_REG2 0x27 -#define SN5S330_INT_MASK_RISE_REG3 0x28 -#define SN5S330_INT_MASK_FALL_REG1 0x29 -#define SN5S330_INT_MASK_FALL_REG2 0x2A -#define SN5S330_INT_MASK_FALL_REG3 0x2B - -#define PPX_ILIM_DEGLITCH_0_US_20 0x1 -#define PPX_ILIM_DEGLITCH_0_US_50 0x2 -#define PPX_ILIM_DEGLITCH_0_US_100 0x3 -#define PPX_ILIM_DEGLITCH_0_US_200 0x4 -#define PPX_ILIM_DEGLITCH_0_US_1000 0x5 -#define PPX_ILIM_DEGLITCH_0_US_2000 0x6 -#define PPX_ILIM_DEGLITCH_0_US_10000 0x7 - -/* Internal VBUS Switch Current Limit Settings (min) */ -#define SN5S330_ILIM_0_35 0 -#define SN5S330_ILIM_0_63 1 -#define SN5S330_ILIM_0_90 2 -#define SN5S330_ILIM_1_14 3 -#define SN5S330_ILIM_1_38 4 -#define SN5S330_ILIM_1_62 5 -#define SN5S330_ILIM_1_86 6 -#define SN5S330_ILIM_2_10 7 -#define SN5S330_ILIM_2_34 8 -#define SN5S330_ILIM_2_58 9 -#define SN5S330_ILIM_2_82 10 -#define SN5S330_ILIM_3_06 11 -#define SN5S330_ILIM_3_30 12 - -/* FUNC_SET_2 */ -#define SN5S330_SBU_EN BIT(4) - -/* FUNC_SET_3 */ -#define SN5S330_PP1_EN BIT(0) -#define SN5S330_PP2_EN BIT(1) -#define SN5S330_VBUS_DISCH_EN BIT(2) -#define SN5S330_SET_RCP_MODE_PP1 BIT(5) -#define SN5S330_SET_RCP_MODE_PP2 BIT(6) - -/* FUNC_SET_4 */ -#define SN5S330_VCONN_EN BIT(0) -#define SN5S330_CC_POLARITY BIT(1) -#define SN5S330_CC_EN BIT(4) -#define SN5S330_VCONN_ILIM_SEL BIT(5) - -/* FUNC_SET_8 */ -#define SN5S330_VCONN_DEGLITCH_MASK (3 << 6) -#define SN5S330_VCONN_DEGLITCH_63_US (0 << 6) -#define SN5S330_VCONN_DEGLITCH_125_US BIT(6) -#define SN5S330_VCONN_DEGLITCH_640_US (2 << 6) -#define SN5S330_VCONN_DEGLITCH_1280_US (3 << 6) - -/* FUNC_SET_9 */ -#define SN5S330_FORCE_OVP_EN_SBU BIT(1) -#define SN5S330_PP2_CONFIG BIT(2) -#define SN5S330_OVP_EN_CC BIT(4) -#define SN5S330_CONFIG_UVP BIT(5) -#define SN5S330_FORCE_ON_VBUS_OVP BIT(6) -#define SN5S330_FORCE_ON_VBUS_UVP BIT(7) - -/* INT_STATUS_REG3 */ -#define SN5S330_VBUS_GOOD BIT(0) - -/* INT_STATUS_REG4 */ -#define SN5S330_DIG_RES BIT(0) -#define SN5S330_DB_BOOT BIT(1) -#define SN5S330_VSAFE0V_STAT BIT(2) -#define SN5S330_VSAFE0V_MASK BIT(3) - -/* - * INT_MASK_RISE/FALL_EDGE_1 - * - * The ILIM_PP1 bit indicates an overcurrent condition when sourcing on power - * path 1. For rising edge registers, this indicates an overcurrent has - * occured; similarly for falling edge, it means the overcurrent condition is no - * longer present. - */ -#define SN5S330_ILIM_PP1_MASK BIT(4) - -/* - * INT_MASK_RISE/FALL_EDGE2 - * - * The VCONN_ILIM bit indicates an overcurrent condition on VCONN. By default, - * VCONN will be latched off. - */ -#define SN5S330_VCONN_ILIM (1 << 1) - -/* - * INT_MASK_RISE/FALL_EDGE2 - * - * The OV_CC1_CON/OV_CC2_CON bit indicates an over-voltage occurred on - * C_CC1/C_CC2. - */ -#define SN5S330_CC1_CON (1 << 2) -#define SN5S330_CC2_CON (1 << 3) - -/* - * INT_MASK_RISE/FALL_EDGE_3 - * - * The VBUS_GOOD bit indicates VBUS has increased beyond a 4.0V threshold. - * For rising edge registers, this indicates VBUS has risen above 4.0V. - * For falling edge registers, this indicates VBUS has fallen below 4.0V. - */ -#define SN5S330_VBUS_GOOD_MASK BIT(0) - -extern const struct ppc_drv sn5s330_drv; - -/** - * Interrupt Handler for the SN5S330. - * - * By default, the only interrupt sources that are unmasked are overcurrent - * conditions for PP1, and VBUS_GOOD if PPC is being used to detect VBUS - * (CONFIG_USB_PD_VBUS_DETECT_PPC). - * - * @param port: The Type-C port which triggered the interrupt. - */ -void sn5s330_interrupt(int port); - -#endif /* defined(__CROS_EC_SN5S330_H) */ diff --git a/driver/ppc/syv682x.c b/driver/ppc/syv682x.c deleted file mode 100644 index 9e0ff28388..0000000000 --- a/driver/ppc/syv682x.c +++ /dev/null @@ -1,351 +0,0 @@ -/* Copyright 2018 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. - */ - -/* Silergy SYV682x USB-C Power Path Controller */ -#include "common.h" -#include "console.h" -#include "driver/ppc/syv682x.h" -#include "i2c.h" -#include "usb_charge.h" -#include "usb_pd_tcpm.h" -#include "usbc_ppc.h" -#include "util.h" - -#define SYV682X_FLAGS_SOURCE_ENABLED BIT(0) -/* 0 -> CC1, 1 -> CC2 */ -#define SYV682X_FLAGS_CC_POLARITY BIT(1) -#define SYV682X_FLAGS_VBUS_PRESENT BIT(2) -static uint8_t flags[CONFIG_USB_PD_PORT_MAX_COUNT]; - -#define SYV682X_VBUS_DET_THRESH_MV 4000 - -static int read_reg(uint8_t port, int reg, int *regval) -{ - return i2c_read8(ppc_chips[port].i2c_port, - ppc_chips[port].i2c_addr_flags, - reg, - regval); -} - -static int write_reg(uint8_t port, int reg, int regval) -{ - return i2c_write8(ppc_chips[port].i2c_port, - ppc_chips[port].i2c_addr_flags, - reg, - regval); -} - -static int syv682x_is_sourcing_vbus(int port) -{ - return flags[port] & SYV682X_FLAGS_SOURCE_ENABLED; -} - -static int syv682x_vbus_sink_enable(int port, int enable) -{ - int regval; - int rv; - - /* - * For sink mode need to make sure high voltage power path is connected - * and sink mode is selected. - */ - rv = read_reg(port, SYV682X_CONTROL_1_REG, ®val); - if (rv) - return rv; - - if (enable) { - /* Select high voltage path */ - regval |= SYV682X_CONTROL_1_CH_SEL; - /* Select Sink mode and turn on the channel */ - regval &= ~(SYV682X_CONTROL_1_HV_DR | - SYV682X_CONTROL_1_PWR_ENB); - } else { - /* - * No need to change the voltage path or channel direction. But, - * turn both paths off. - */ - regval |= SYV682X_CONTROL_1_PWR_ENB; - } - - return write_reg(port, SYV682X_CONTROL_1_REG, regval); -} - -#ifdef CONFIG_USB_PD_VBUS_DETECT_PPC -static int syv682x_is_vbus_present(int port) -{ - int val; - int vbus = 0; - - /* - * TODO (b/112661747): This PPC doesn't fully support VBUS detection. - * It can detect both VSafe5V and VSafe0V. This function is intended - * here until detecting VBUS differently per channel is supported. - */ - if (read_reg(port, SYV682X_STATUS_REG, &val)) - return vbus; - - /* - * VBUS is considered present if VSafe5V is detected or neither VSafe5V - * or VSafe0V is detected, which implies VBUS > 5V. - */ - if ((val & SYV682X_STATUS_VSAFE_5V) || - !(val & (SYV682X_STATUS_VSAFE_5V | SYV682X_STATUS_VSAFE_0V))) - vbus = 1; -#ifdef CONFIG_USB_CHARGER - if (!!(flags[port] & SYV682X_FLAGS_VBUS_PRESENT) != vbus) - usb_charger_vbus_change(port, vbus); - - if (vbus) - flags[port] |= SYV682X_FLAGS_VBUS_PRESENT; - else - flags[port] &= ~SYV682X_FLAGS_VBUS_PRESENT; -#endif - - return vbus; -} -#endif - -static int syv682x_vbus_source_enable(int port, int enable) -{ - int regval; - int rv; - - /* - * For source mode need to make sure 5V power path is connected - * and source mode is selected. - */ - rv = read_reg(port, SYV682X_CONTROL_1_REG, ®val); - if (rv) - return rv; - - if (enable) { - /* Select 5V path and turn on channel */ - regval &= ~(SYV682X_CONTROL_1_CH_SEL | - SYV682X_CONTROL_1_PWR_ENB); - /* Disable HV Sink path */ - regval |= SYV682X_CONTROL_1_HV_DR; - } else if (flags[port] & SYV682X_FLAGS_SOURCE_ENABLED) { - /* - * For the disable case, make sure that VBUS was being sourced - * prior to disabling the source path. Because the source/sink - * paths can't be independently disabled, and this function will - * get called as part of USB PD initialization, setting the - * PWR_ENB always can lead to broken dead battery behavior. - * - * No need to change the voltage path or channel direction. But, - * turn both paths off. - */ - regval |= SYV682X_CONTROL_1_PWR_ENB; - } - - rv = write_reg(port, SYV682X_CONTROL_1_REG, regval); - if (rv) - return rv; - - if (enable) - flags[port] |= SYV682X_FLAGS_SOURCE_ENABLED; - else - flags[port] &= ~SYV682X_FLAGS_SOURCE_ENABLED; - -#if defined(CONFIG_USB_CHARGER) && defined(CONFIG_USB_PD_VBUS_DETECT_PPC) - /* - * Since the VBUS state could be changing here, need to wake the - * USB_CHG_N task so that BC 1.2 detection will be triggered. - */ - usb_charger_vbus_change(port, enable); -#endif - - return EC_SUCCESS; -} - -static int syv682x_set_vbus_source_current_limit(int port, - enum tcpc_rp_value rp) -{ - int rv; - int limit; - int regval; - - rv = read_reg(port, SYV682X_CONTROL_1_REG, ®val); - if (rv) - return rv; - - /* We need buffer room for all current values. */ - switch (rp) { - case TYPEC_RP_3A0: - limit = SYV682X_ILIM_3_30; - break; - - case TYPEC_RP_1A5: - limit = SYV682X_ILIM_1_75; - break; - - case TYPEC_RP_USB: - default: - /* 1.25 A is lowest current limit setting for SVY682 */ - limit = SYV682X_ILIM_1_25; - break; - }; - - regval &= ~SYV682X_ILIM_MASK; - regval |= (limit << SYV682X_ILIM_BIT_SHIFT); - return write_reg(port, SYV682X_CONTROL_1_REG, regval); -} - -static int syv682x_discharge_vbus(int port, int enable) -{ - int regval; - int rv; - - rv = read_reg(port, SYV682X_CONTROL_2_REG, ®val); - if (rv) - return rv; - - if (enable) - regval |= SYV682X_CONTROL_2_FDSG; - else - regval &= ~SYV682X_CONTROL_2_FDSG; - - return write_reg(port, SYV682X_CONTROL_2_REG, regval); -} - -#ifdef CONFIG_USBC_PPC_POLARITY -static int syv682x_set_polarity(int port, int polarity) -{ - /* - * The SYV682x does not explicitly set CC polarity. However, if VCONN is - * being used then the polarity is required to connect 5V to the correct - * CC line. So this function saves the CC polarity as a bit in the flags - * variable so VCONN is connected the correct CC line. The flag bit - * being set means polarity = CC2, the flag bit clear means - * polarity = CC1. - */ - if (polarity) - flags[port] |= SYV682X_FLAGS_CC_POLARITY; - else - flags[port] &= ~SYV682X_FLAGS_CC_POLARITY; - - return EC_SUCCESS; -} -#endif - -#ifdef CONFIG_USBC_PPC_VCONN -static int syv682x_set_vconn(int port, int enable) -{ - int regval; - int rv; - - rv = read_reg(port, SYV682X_CONTROL_4_REG, ®val); - if (rv) - return rv; - - if (enable) - regval |= flags[port] & SYV682X_FLAGS_CC_POLARITY ? - SYV682X_CONTROL_4_VCONN1 : SYV682X_CONTROL_4_VCONN2; - else - regval &= ~(SYV682X_CONTROL_4_VCONN2 | - SYV682X_CONTROL_4_VCONN1); - - return write_reg(port, SYV682X_CONTROL_4_REG, regval); -} -#endif - -#ifdef CONFIG_CMD_PPC_DUMP -static int syv682x_dump(int port) -{ - int reg_addr; - int data; - int rv; - const int i2c_port = ppc_chips[port].i2c_port; - const int i2c_addr_flags = ppc_chips[port].i2c_addr_flags; - - for (reg_addr = SYV682X_STATUS_REG; reg_addr <= SYV682X_CONTROL_4_REG; - reg_addr++) { - rv = i2c_read8(i2c_port, i2c_addr_flags, reg_addr, &data); - if (rv) - ccprintf("ppc_syv682[p%d]: Failed to read reg 0x%02x\n", - port, reg_addr); - else - ccprintf("ppc_syv682[p%d]: reg 0x%02x = 0x%02x\n", - port, reg_addr, data); - } - - cflush(); - - return EC_SUCCESS; -} -#endif /* defined(CONFIG_CMD_PPC_DUMP) */ - -static int syv682x_init(int port) -{ - int rv; - int regval; - - /* Set VBUS discharge to manual mode */ - rv = read_reg(port, SYV682X_CONTROL_2_REG, ®val); - if (rv) - return rv; - regval &= ~SYV682X_CONTROL_2_SDSG; - rv = write_reg(port, SYV682X_CONTROL_2_REG, regval); - if (rv) - return rv; - - /* Select max voltage for OVP */ - rv = read_reg(port, SYV682X_CONTROL_3_REG, ®val); - if (rv) - return rv; - regval &= ~SYV682X_OVP_MASK; - regval |= (SYV682X_OVP_23_7 << SYV682X_OVP_BIT_SHIFT); - rv = write_reg(port, SYV682X_CONTROL_3_REG, regval); - if (rv) - return rv; - - /* Check if this if dead battery case */ - rv = read_reg(port, SYV682X_CONTROL_1_REG, ®val); - if (rv) - return rv; - if (regval & SYV682X_STATUS_VSAFE_0V) { - /* Not dead battery case, so disable channel */ - regval |= SYV682X_CONTROL_1_PWR_ENB; - rv = write_reg(port, SYV682X_CONTROL_1_REG, regval); - if (rv) - return rv; - } else { - syv682x_vbus_sink_enable(port, 1); - } - - rv = read_reg(port, SYV682X_CONTROL_4_REG, ®val); - if (rv) - return rv; - /* Remove Rd and connect CC1/CC2 lines to TCPC */ - regval |= SYV682X_CONTROL_4_CC1_BPS | SYV682X_CONTROL_4_CC2_BPS; - /* Disable Fast Role Swap (FRS) */ - regval |= SYV682X_CONTROL_4_CC_FRS; - rv = write_reg(port, SYV682X_CONTROL_4_REG, regval); - if (rv) - return rv; - - return EC_SUCCESS; -} - -const struct ppc_drv syv682x_drv = { - .init = &syv682x_init, - .is_sourcing_vbus = &syv682x_is_sourcing_vbus, - .vbus_sink_enable = &syv682x_vbus_sink_enable, - .vbus_source_enable = &syv682x_vbus_source_enable, -#ifdef CONFIG_CMD_PPC_DUMP - .reg_dump = &syv682x_dump, -#endif /* defined(CONFIG_CMD_PPC_DUMP) */ -#ifdef CONFIG_USB_PD_VBUS_DETECT_PPC - .is_vbus_present = &syv682x_is_vbus_present, -#endif /* defined(CONFIG_USB_PD_VBUS_DETECT_PPC) */ - .set_vbus_source_current_limit = &syv682x_set_vbus_source_current_limit, - .discharge_vbus = &syv682x_discharge_vbus, -#ifdef CONFIG_USBC_PPC_POLARITY - .set_polarity = &syv682x_set_polarity, -#endif -#ifdef CONFIG_USBC_PPC_VCONN - .set_vconn = &syv682x_set_vconn, -#endif -}; diff --git a/driver/ppc/syv682x.h b/driver/ppc/syv682x.h deleted file mode 100644 index 4a76659f41..0000000000 --- a/driver/ppc/syv682x.h +++ /dev/null @@ -1,68 +0,0 @@ -/* Copyright 2018 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. - */ - -/* Silergy SYV682x Type-C Power Path Controller */ - -#ifndef __CROS_EC_SYV682X_H -#define __CROS_EC_SYV682X_H - -/* I2C addresses */ -#define SYV682X_ADDR0_FLAGS 0x40 -#define SYV682X_ADDR1_FLAGS 0x41 -#define SYV682X_ADDR2_FLAGS 0x42 -#define SYV682x_ADDR3_FLAGS 0x43 - -/* SYV682x register addresses */ -#define SYV682X_STATUS_REG 0x00 -#define SYV682X_CONTROL_1_REG 0x01 -#define SYV682X_CONTROL_2_REG 0x02 -#define SYV682X_CONTROL_3_REG 0x03 -#define SYV682X_CONTROL_4_REG 0x04 - -/* Status Register */ -#define SYV682X_STATUS_VSAFE_5V BIT(1) -#define SYV682X_STATUS_VSAFE_0V BIT(0) - -/* Control Register 1 */ -#define SYV682X_CONTROL_1_CH_SEL BIT(1) -#define SYV682X_CONTROL_1_HV_DR BIT(2) -#define SYV682X_CONTROL_1_PWR_ENB BIT(7) - -#define SYV682X_ILIM_MASK 0x18 -#define SYV682X_ILIM_BIT_SHIFT 3 -#define SYV682X_ILIM_1_25 0 -#define SYV682X_ILIM_1_75 1 -#define SYV682X_ILIM_2_25 2 -#define SYV682X_ILIM_3_30 3 - -/* Control Register 2 */ -#define SYV682X_CONTROL_2_SDSG BIT(1) -#define SYV682X_CONTROL_2_FDSG BIT(0) - -/* Control Register 3 */ -#define SYV682X_OVP_MASK 0x70 -#define SYV682X_OVP_BIT_SHIFT 4 -#define SYV682X_OVP_06_0 0 -#define SYV682X_OVP_08_0 1 -#define SYV682X_OVP_11_1 2 -#define SYV682X_OVP_12_1 3 -#define SYV682X_OVP_14_2 4 -#define SYV682X_OVP_17_9 5 -#define SYV682X_OVP_21_6 6 -#define SYV682X_OVP_23_7 7 - -/* Control Register 4 */ -#define SYV682X_CONTROL_4_CC1_BPS BIT(7) -#define SYV682X_CONTROL_4_CC2_BPS BIT(6) -#define SYV682X_CONTROL_4_VCONN1 BIT(5) -#define SYV682X_CONTROL_4_VCONN2 BIT(4) -#define SYV682X_CONTROL_4_VBAT_OVP BIT(3) -#define SYV682X_CONTROL_4_VCONN_OCP BIT(2) -#define SYV682X_CONTROL_4_CC_FRS BIT(1) - -struct ppc_drv; -extern const struct ppc_drv syv682x_drv; - -#endif /* defined(__CROS_EC_SYV682X_H) */ diff --git a/driver/regulator_ir357x.c b/driver/regulator_ir357x.c deleted file mode 100644 index 4721146367..0000000000 --- a/driver/regulator_ir357x.c +++ /dev/null @@ -1,247 +0,0 @@ -/* Copyright 2012 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. - * - * IR357x driver. - */ - -#include "common.h" -#include "console.h" -#include "hooks.h" -#include "i2c.h" -#include "timer.h" -#include "util.h" - -/* Console output macros */ -#define CPUTS(outstr) cputs(CC_CHIPSET, outstr) -#define CPRINTF(format, args...) cprintf(CC_CHIPSET, format, ## args) - -/* I2C address */ -#define IR357x_I2C_ADDR_FLAGS 0x08 - -struct ir_setting { - uint8_t reg; - uint8_t value; -}; - -static struct ir_setting ir3570_settings[] = { - {0x10, 0x22}, {0x11, 0x22}, {0x12, 0x88}, {0x13, 0x10}, - {0x14, 0x0d}, {0x15, 0x21}, {0x16, 0x21}, {0x17, 0x00}, - {0x18, 0x00}, {0x19, 0x00}, {0x1a, 0x00}, {0x1b, 0x00}, - {0x1c, 0x00}, {0x1d, 0x00}, {0x1e, 0x00}, {0x1f, 0x00}, - {0x20, 0x00}, {0x21, 0x00}, {0x22, 0x60}, {0x23, 0x60}, - {0x24, 0x74}, {0x25, 0x4e}, {0x26, 0xff}, {0x27, 0x80}, - {0x28, 0x00}, {0x29, 0x20}, {0x2a, 0x15}, {0x2b, 0x26}, - {0x2c, 0xb6}, {0x2d, 0x21}, {0x2e, 0x11}, {0x2f, 0x20}, - {0x30, 0xab}, {0x31, 0x14}, {0x32, 0x90}, {0x33, 0x4d}, - {0x34, 0x75}, {0x35, 0x64}, {0x36, 0x64}, {0x37, 0x09}, - {0x38, 0xc4}, {0x39, 0x20}, {0x3a, 0x80}, {0x3b, 0x00}, - {0x3c, 0x00}, {0x3d, 0xaa}, {0x3e, 0x00}, {0x3f, 0x05}, - {0x40, 0x50}, {0x41, 0x40}, {0x42, 0x00}, {0x43, 0x00}, - {0x44, 0x00}, {0x45, 0x00}, {0x46, 0x00}, {0x47, 0x00}, - {0x48, 0x1c}, {0x49, 0x0c}, {0x4a, 0x0f}, {0x4b, 0x40}, - {0x4c, 0x80}, {0x4d, 0x40}, {0x4e, 0x80}, - {0x51, 0x00}, {0x52, 0x45}, {0x53, 0x59}, - {0x54, 0x23}, {0x55, 0xae}, {0x56, 0x68}, {0x57, 0x24}, - {0x58, 0x62}, {0x59, 0x42}, {0x5a, 0x34}, {0x5b, 0x00}, - {0x5c, 0x30}, {0x5d, 0x05}, {0x5e, 0x02}, {0x5f, 0x35}, - {0x60, 0x30}, {0x61, 0x00}, {0x62, 0xd8}, {0x63, 0x00}, - {0x64, 0x52}, {0x65, 0x28}, {0x66, 0x14}, {0x67, 0x87}, - {0x68, 0x80}, {0x69, 0x00}, {0x6a, 0x00}, {0x6b, 0x00}, - {0x6c, 0x00}, {0x6d, 0xff}, {0x6e, 0x06}, {0x6f, 0xff}, - {0x70, 0xff}, {0x71, 0x20}, {0x72, 0x00}, {0x73, 0x01}, - {0x74, 0x00}, {0x75, 0x00}, {0x76, 0x00}, {0x77, 0x00}, - {0x78, 0x00}, {0x79, 0x00}, {0x7a, 0x00}, {0x7b, 0x00}, - {0x7c, 0x15}, {0x7d, 0x15}, {0x7e, 0x00}, {0x7f, 0x00}, - {0x80, 0x00}, {0x81, 0x00}, {0x82, 0x00}, {0x83, 0x00}, - {0x84, 0x00}, {0x85, 0x00}, {0x86, 0x00}, {0x87, 0x00}, - {0x88, 0x88}, {0x89, 0x88}, {0x8a, 0x01}, {0x8b, 0x42}, - {0x8d, 0x00}, {0x8e, 0x00}, {0x8f, 0x1f}, - {0, 0} -}; - -static struct ir_setting ir3571_settings[] = { - {0x18, 0x22}, {0x19, 0x22}, {0x1a, 0x08}, {0x1b, 0x10}, - {0x1c, 0x06}, {0x1d, 0x21}, {0x1e, 0x21}, {0x1f, 0x83}, - {0x20, 0x83}, {0x21, 0x00}, {0x22, 0x00}, {0x23, 0x00}, - {0x24, 0x00}, {0x25, 0x00}, {0x26, 0x00}, {0x27, 0x34}, - {0x28, 0x34}, {0x29, 0x74}, {0x2a, 0x4e}, {0x2b, 0xff}, - {0x2c, 0x00}, {0x2d, 0x1d}, {0x2e, 0x14}, {0x2f, 0x1f}, - {0x30, 0x88}, {0x31, 0x9a}, {0x32, 0x1e}, {0x33, 0x19}, - {0x34, 0xe9}, {0x35, 0x40}, {0x36, 0x90}, {0x37, 0x6d}, - {0x38, 0x75}, {0x39, 0xa0}, {0x3a, 0x84}, {0x3b, 0x08}, - {0x3c, 0xc5}, {0x3d, 0xa0}, {0x3e, 0x80}, {0x3f, 0xaa}, - {0x40, 0x50}, {0x41, 0x4b}, {0x42, 0x02}, {0x43, 0x04}, - {0x44, 0x00}, {0x45, 0x00}, {0x46, 0x00}, {0x47, 0x78}, - {0x48, 0x56}, {0x49, 0x18}, {0x4a, 0x88}, {0x4b, 0x00}, - {0x4c, 0x80}, {0x4d, 0x60}, {0x4e, 0x60}, {0x4f, 0xff}, - {0x50, 0xff}, {0x51, 0x00}, {0x52, 0x9b}, {0x53, 0xaa}, - {0x54, 0xd8}, {0x55, 0x56}, {0x56, 0x31}, {0x57, 0x1a}, - {0x58, 0x12}, {0x59, 0x63}, {0x5a, 0x00}, {0x5b, 0x09}, - {0x5c, 0x02}, {0x5d, 0x00}, {0x5e, 0xea}, {0x5f, 0x00}, - {0x60, 0xb0}, {0x61, 0x1e}, {0x62, 0x00}, {0x63, 0x56}, - {0x64, 0x00}, {0x65, 0x00}, {0x66, 0x00}, {0x67, 0x00}, - {0x68, 0x28}, {0x69, 0x00}, {0x6a, 0x00}, {0x6b, 0x00}, - {0x6c, 0x00}, {0x6d, 0x00}, {0x6e, 0x00}, {0x6f, 0x00}, - {0x70, 0x80}, {0x71, 0x00}, {0x72, 0x00}, {0x73, 0x00}, - {0x74, 0x00}, {0x75, 0xbf}, {0x76, 0x06}, {0x77, 0xff}, - {0x78, 0xff}, {0x79, 0x04}, {0x7a, 0x00}, {0x7b, 0x1d}, - {0x7c, 0xa0}, {0x7d, 0x10}, {0x7e, 0x00}, {0x7f, 0x8a}, - {0x80, 0x1b}, {0x81, 0x11}, {0x82, 0x00}, {0x83, 0x00}, - {0x84, 0x00}, {0x85, 0x00}, {0x86, 0x00}, {0x87, 0x00}, - {0x88, 0x00}, {0x89, 0x00}, {0x8a, 0x00}, {0x8b, 0x00}, - {0x8c, 0x00}, {0x8d, 0x00}, {0x8e, 0x00}, {0x8f, 0x00}, - {0, 0} -}; - -static uint8_t ir357x_read(uint8_t reg) -{ - int res; - int val; - - res = i2c_read8(I2C_PORT_REGULATOR, IR357x_I2C_ADDR, reg, &val); - if (res) - return 0xee; - - return val; -} - -static void ir357x_write(uint8_t reg, uint8_t val) -{ - int res; - - res = i2c_write8(I2C_PORT_REGULATOR, IR357x_I2C_ADDR, reg, val); - if (res) - CPRINTF("IR I2C write failed\n"); -} - -static int ir357x_get_version(void) -{ - /* IR3571 on Link EVT */ - if ((ir357x_read(0xfc) == 'I') && (ir357x_read(0xfd) == 'R') && - ((ir357x_read(0x0a) & 0xe) == 0)) - return 3571; - - /* IR3570A on Link Proto 0/1 and Link DVT */ - if ((ir357x_read(0x92) == 'C') && (ir357x_read(0xcd) == 0x24)) - return 3570; - - /* Unknown and unsupported chip */ - return -1; -} - -struct ir_setting *ir357x_get_settings(void) -{ - int version = ir357x_get_version(); - - if (version == 3570) - return ir3570_settings; - else if (version == 3571) - return ir3571_settings; - else - return NULL; -} - -static void ir357x_prog(void) -{ - struct ir_setting *settings = ir357x_get_settings(); - - if (settings) { - for (; settings->reg; settings++) - ir357x_write(settings->reg, settings->value); - } else { - CPRINTF("IR%d chip unsupported. Skip writing settings!\n", - ir357x_get_version()); - return; - } - - CPRINTF("IR%d registers UPDATED\n", ir357x_get_version()); -} - -static void ir357x_dump(void) -{ - int i; - - for (i = 0; i < 256; i++) { - if (!(i & 0xf)) { - ccprintf("\n%02x: ", i); - cflush(); - } - ccprintf("%02x ", ir357x_read(i)); - } - ccprintf("\n"); -} - -static int ir357x_check(void) -{ - uint8_t val; - int diff = 0; - struct ir_setting *settings = ir357x_get_settings(); - - if (!settings) { - ccprintf("no setting for chip IR%d !\n", ir357x_get_version()); - return 1; - } - - for (; settings->reg; settings++) { - val = ir357x_read(settings->reg); - if (val != settings->value) { - ccprintf("DIFF reg 0x%02x %02x->%02x\n", - settings->reg, settings->value, val); - cflush(); - diff++; - } - } - return !!diff; -} - -#ifdef CONFIG_CMD_REGULATOR -static int command_ir357x(int argc, char **argv) -{ - int reg, val; - char *rem; - - if (1 == argc) { /* dump all registers */ - ir357x_dump(); - return EC_SUCCESS; - } else if (2 == argc) { - if (!strcasecmp(argv[1], "check")) { - ir357x_check(); - } else { /* read one register */ - reg = strtoi(argv[1], &rem, 16); - if (*rem) { - ccprintf("Invalid register: %s\n", argv[1]); - return EC_ERROR_INVAL; - } - ccprintf("reg 0x%02x = 0x%02x\n", reg, - ir357x_read(reg)); - } - return EC_SUCCESS; - } else if (3 == argc) { /* write one register */ - reg = strtoi(argv[1], &rem, 16); - if (*rem) { - ccprintf("Invalid register: %s\n", argv[1]); - return EC_ERROR_INVAL; - } - val = strtoi(argv[2], &rem, 16); - if (*rem) { - ccprintf("Invalid value: %s\n", argv[2]); - return EC_ERROR_INVAL; - } - ir357x_write(reg, val); - return EC_SUCCESS; - } - - return EC_ERROR_INVAL; -} -DECLARE_CONSOLE_COMMAND(ir357x, command_ir357x, - "[check|write]", - "IR357x core regulator control"); -#endif - -static void ir357x_hot_settings(void) -{ - /* dynamically apply settings to workaround issue */ - ir357x_prog(); -} -DECLARE_HOOK(HOOK_CHIPSET_RESUME, ir357x_hot_settings, HOOK_PRIO_DEFAULT); diff --git a/driver/retimer/bb_retimer.c b/driver/retimer/bb_retimer.c deleted file mode 100644 index 9a0caf5c4e..0000000000 --- a/driver/retimer/bb_retimer.c +++ /dev/null @@ -1,290 +0,0 @@ -/* Copyright 2019 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. - * - * Driver for Intel Burnside Bridge - Thunderbolt/USB/DisplayPort Retimer - */ - -#include "bb_retimer.h" -#include "common.h" -#include "console.h" -#include "i2c.h" -#include "timer.h" -#include "usb_pd.h" -#include "util.h" - -#define BB_RETIMER_REG_SIZE 4 -#define BB_RETIMER_READ_SIZE (BB_RETIMER_REG_SIZE + 1) -#define BB_RETIMER_WRITE_SIZE (BB_RETIMER_REG_SIZE + 2) - -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args) - -/** - * Utility functions - */ -static int bb_retimer_read(int port, const uint8_t offset, uint32_t *data) -{ - int rv; - uint8_t buf[BB_RETIMER_READ_SIZE]; - - /* - * Read sequence - * Slave Addr(w) - Reg offset - repeated start - Slave Addr(r) - * byte[0] : Read size - * byte[1:4] : Data [LSB -> MSB] - * Stop - */ - rv = i2c_xfer(usb_retimers[port].i2c_port, - usb_retimers[port].i2c_addr_flags, - &offset, 1, buf, BB_RETIMER_READ_SIZE); - if (rv) - return rv; - if (buf[0] != BB_RETIMER_REG_SIZE) - return EC_ERROR_UNKNOWN; - - *data = buf[1] | (buf[2] << 8) | (buf[3] << 16) | (buf[4] << 24); - - return EC_SUCCESS; -} - -static int bb_retimer_write(int port, const uint8_t offset, uint32_t data) -{ - uint8_t buf[BB_RETIMER_WRITE_SIZE]; - - /* - * Write sequence - * Slave Addr(w) - * byte[0] : Reg offset - * byte[1] : Write Size - * byte[2:5] : Data [LSB -> MSB] - * stop - */ - buf[0] = offset; - buf[1] = BB_RETIMER_REG_SIZE; - buf[2] = data & 0xFF; - buf[3] = (data >> 8) & 0xFF; - buf[4] = (data >> 16) & 0xFF; - buf[5] = (data >> 24) & 0xFF; - - return i2c_xfer(usb_retimers[port].i2c_port, - usb_retimers[port].i2c_addr_flags, - buf, BB_RETIMER_WRITE_SIZE, NULL, 0); -} - -static void bb_retimer_power_handle(int port, int on_off) -{ - const struct usb_retimer * const retimer = &usb_retimers[port]; - - /* handle retimer's power domain */ - - if (on_off) { - gpio_set_level(retimer->usb_ls_en_gpio, 1); - msleep(1); - gpio_set_level(retimer->retimer_rst_gpio, 1); - msleep(10); - gpio_set_level(retimer->force_power_gpio, 1); - - /* - * If BB retimer NVM is shared between two ports allow 40ms - * time for both retimers to be initialized. Else allow 20ms - * to initialize. - */ - if ((USB_PORT0_BB_RETIMER_SHARED_NVM && - (port == TYPE_C_PORT_0)) || - (USB_PORT1_BB_RETIMER_SHARED_NVM && - (port == TYPE_C_PORT_1))) - msleep(40); - else - msleep(20); - } else { - gpio_set_level(retimer->force_power_gpio, 0); - msleep(1); - gpio_set_level(retimer->retimer_rst_gpio, 0); - msleep(1); - gpio_set_level(retimer->usb_ls_en_gpio, 0); - } -} - -/** - * Driver interface functions - */ -static int retimer_set_state(int port, mux_state_t mux_state) -{ - uint32_t set_retimer_con = 0; - uint8_t dp_pin_mode; - - /* - * Bit 0: DATA_CONNECTION_PRESENT - * 0 - No connection present - * 1 - Connection present - */ - if (mux_state & USB_PD_MUX_USB_ENABLED || - mux_state & USB_PD_MUX_DP_ENABLED) - set_retimer_con |= BB_RETIMER_DATA_CONNECTION_PRESENT; - - /* - * Bit 1: CONNECTION_ORIENTATION - * 0 - Normal - * 1 - reversed - */ - if (mux_state & USB_PD_MUX_POLARITY_INVERTED) - set_retimer_con |= BB_RETIMER_CONNECTION_ORIENTATION; - - /* - * TODO: b:129990370 - * Bit 2: ACTIVE_CABLE - * 0 - Passive - * 1 -TBT Active cable - */ - - /* - * Bit 5: USB_3_CONNECTION - * 0 - No USB3.1 Connection - * 1 - USB3.1 connection - */ - if (mux_state & USB_PD_MUX_USB_ENABLED) { - set_retimer_con |= BB_RETIMER_USB_3_CONNECTION; - - /* - * Bit 7: USB_DATA_ROLE (ignored if BIT5=0) - * 0 - DFP - * 1 - UPF - */ - if (pd_partner_is_ufp(port)) - set_retimer_con |= BB_RETIMER_USB_DATA_ROLE; - } - - /* - * Bit 8: DP_CONNECTION - * 0 – No DP connection - * 1 – DP connected - */ - if (mux_state & USB_PD_MUX_DP_ENABLED) { - set_retimer_con |= BB_RETIMER_DP_CONNECTION; - - /* - * Bit 10-11: DP_PIN_ASSIGNMENT (ignored if BIT8 = 0) - * 00 – Pin assignments E/E’ - * 01 – Pin assignments C/C’/D/D’1,2 - * 10, 11 - reserved - */ - dp_pin_mode = board_get_dp_pin_mode(port); - if (dp_pin_mode == MODE_DP_PIN_C || - dp_pin_mode == MODE_DP_PIN_D) - set_retimer_con |= BB_RETIMER_DP_PIN_ASSIGNMENT; - - /* - * Bit 14: IRQ_HPD (ignored if BIT8 = 0) - * 0 - No IRQ_HPD - * 1 - IRQ_HPD received - */ - if (mux_state & USB_PD_MUX_HPD_IRQ) - set_retimer_con |= BB_RETIMER_IRQ_HPD; - - /* - * Bit 15: HPD_LVL (ignored if BIT8 = 0) - * 0 - HPD_State Low - * 1 - HPD_State High - */ - if (mux_state & USB_PD_MUX_HPD_LVL) - set_retimer_con |= BB_RETIMER_HPD_LVL; - } - - /* - * Bit 12: DEBUG_ACCESSORY_MODE - * 0 - Not in debug mode - * 1 - In debug accessory mode - */ - if (pd_is_debug_acc(port)) - set_retimer_con |= BB_RETIMER_DEBUG_ACCESSORY_MODE; - - /* Writing the register4 */ - return bb_retimer_write(port, BB_RETIMER_REG_CONNECTION_STATE, - set_retimer_con); -} - -static int retimer_low_power_mode(int port) -{ - bb_retimer_power_handle(port, 0); - return EC_SUCCESS; -} - -static int retimer_init(int port) -{ - int rv; - uint32_t data; - - bb_retimer_power_handle(port, 1); - - rv = bb_retimer_read(port, BB_RETIMER_REG_VENDOR_ID, &data); - if (rv) - return rv; - if (data != BB_RETIMER_VENDOR_ID) - return EC_ERROR_UNKNOWN; - - rv = bb_retimer_read(port, BB_RETIMER_REG_DEVICE_ID, &data); - if (rv) - return rv; - - if (data != BB_RETIMER_DEVICE_ID) - return EC_ERROR_UNKNOWN; - - return EC_SUCCESS; -} - -const struct usb_retimer_driver bb_usb_retimer = { - .init = retimer_init, - .set = retimer_set_state, - .enter_low_power_mode = retimer_low_power_mode, -}; - -#ifdef CONFIG_CMD_RETIMER -static int console_command_bb_retimer(int argc, char **argv) -{ - char rw, *e; - int rv, port, reg, data, val; - - if (argc < 4) - return EC_ERROR_PARAM_COUNT; - - /* Get port number */ - port = strtoi(argv[1], &e, 0); - if (*e || port < 0 || port > board_get_usb_pd_port_count()) - return EC_ERROR_PARAM1; - - /* Validate r/w selection */ - rw = argv[2][0]; - if (rw != 'w' && rw != 'r') - return EC_ERROR_PARAM2; - - /* Get register address */ - reg = strtoi(argv[3], &e, 0); - if (*e || reg < 0) - return EC_ERROR_PARAM3; - - if (rw == 'r') - rv = bb_retimer_read(port, reg, &data); - else { - /* Get value to be written */ - val = strtoi(argv[4], &e, 0); - if (*e || val < 0) - return EC_ERROR_PARAM4; - - rv = bb_retimer_write(port, reg, val); - if (rv == EC_SUCCESS) { - rv = bb_retimer_read(port, reg, &data); - if (rv == EC_SUCCESS && data != val) - rv = EC_ERROR_UNKNOWN; - } - } - - if (rv == EC_SUCCESS) - CPRINTS("register 0x%x [%d] = 0x%x [%d]", reg, reg, data, data); - - return rv; -} -DECLARE_CONSOLE_COMMAND(bb, console_command_bb_retimer, - "<port> <r/w> <reg> | <val>", - "Read or write to BB retimer register"); -#endif /* CONFIG_CMD_RETIMER */ diff --git a/driver/retimer/bb_retimer.h b/driver/retimer/bb_retimer.h deleted file mode 100644 index 0dfa89e5f0..0000000000 --- a/driver/retimer/bb_retimer.h +++ /dev/null @@ -1,37 +0,0 @@ -/* Copyright 2019 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. - * - * Driver header for Intel Burnside Bridge - Thunderbolt/USB/DisplayPort Retimer - */ - -#ifndef __CROS_EC_BB_RETIMER_H -#define __CROS_EC_BB_RETIMER_H - -#include "gpio.h" -#include "usb_mux.h" - -/* Burnside Bridge I2C Configuration Space */ -#define BB_RETIMER_REG_VENDOR_ID 0 -#define BB_RETIMER_VENDOR_ID 0x8086 - -#define BB_RETIMER_REG_DEVICE_ID 1 -#define BB_RETIMER_DEVICE_ID 0x15EE - -/* Connection State Register Attributes */ -#define BB_RETIMER_REG_CONNECTION_STATE 4 -#define BB_RETIMER_DATA_CONNECTION_PRESENT BIT(0) -#define BB_RETIMER_CONNECTION_ORIENTATION BIT(1) -#define BB_RETIMER_ACTIVE_CABLE BIT(2) -#define BB_RETIMER_USB_3_CONNECTION BIT(5) -#define BB_RETIMER_USB_DATA_ROLE BIT(7) -#define BB_RETIMER_DP_CONNECTION BIT(8) -#define BB_RETIMER_DP_PIN_ASSIGNMENT BIT(10) -#define BB_RETIMER_DEBUG_ACCESSORY_MODE BIT(12) -#define BB_RETIMER_IRQ_HPD BIT(14) -#define BB_RETIMER_HPD_LVL BIT(15) - -/* Supported USB retimer drivers */ -extern const struct usb_retimer_driver bb_usb_retimer; - -#endif /* __CROS_EC_BB_RETIMER_H */ diff --git a/driver/retimer/pi3dpx1207.c b/driver/retimer/pi3dpx1207.c deleted file mode 100644 index 8d57dcb6ef..0000000000 --- a/driver/retimer/pi3dpx1207.c +++ /dev/null @@ -1,145 +0,0 @@ -/* Copyright 2019 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. - * - * PI3DPX1207 retimer. - */ - -#include "pi3dpx1207.h" -#include "common.h" -#include "console.h" -#include "gpio.h" -#include "i2c.h" -#include "ioexpander.h" -#include "usb_mux.h" - -#define I2C_MAX_RETRIES 2 - -/* Stack space is limited, so put the buffer somewhere else */ -static uint8_t buf[PI3DPX1207_NUM_REGISTERS]; - -/** - * Local utility functions - */ -static int pi3dpx1207_i2c_write(int i2c_port, - uint16_t addr_flags, - uint8_t offset, - uint8_t val) -{ - int rv = EC_SUCCESS; - int attempt; - - if (offset >= PI3DPX1207_NUM_REGISTERS) - return EC_ERROR_INVAL; - - /* - * PI3DPX1207 does not support device register offset in - * the typical I2C sense. Have to read the values starting - * from 0, modify the byte and then write the block. - * - * NOTE: The device may not respond correctly if it was - * just powered or has gone to sleep. Allow for retries - * in case this happens. - */ - if (offset > 0) { - attempt = 0; - do { - attempt++; - rv = i2c_xfer(i2c_port, addr_flags, - NULL, 0, buf, offset); - } while ((rv != EC_SUCCESS) && (attempt < I2C_MAX_RETRIES)); - } - - if (rv == EC_SUCCESS) { - buf[offset] = val; - - attempt = 0; - do { - attempt++; - rv = i2c_xfer(i2c_port, addr_flags, - buf, offset + 1, NULL, 0); - } while ((rv != EC_SUCCESS) && (attempt < I2C_MAX_RETRIES)); - } - return rv; -} - -static void pi3dpx1207_shutoff_power(int port) -{ - const int gpio_enable = usb_retimers[port].gpio_enable; - const int gpio_dp_enable = usb_retimers[port].gpio_dp_enable; - - gpio_or_ioex_set_level(gpio_enable, 0); - gpio_or_ioex_set_level(gpio_dp_enable, 0); -} - -/** - * Driver interface code - */ -static int pi3dpx1207_init(int port) -{ - const int gpio_enable = usb_retimers[port].gpio_enable; - - gpio_or_ioex_set_level(gpio_enable, 1); - return EC_SUCCESS; -} - -static int pi3dpx1207_enter_low_power_mode(int port) -{ - pi3dpx1207_shutoff_power(port); - return EC_SUCCESS; -} - -static int pi3dpx1207_set_mux(int port, mux_state_t mux_state) -{ - int rv = EC_SUCCESS; - uint8_t mode_val = PI3DPX1207_MODE_WATCHDOG_EN; - - const int i2c_port = usb_retimers[port].i2c_port; - const uint16_t i2c_addr_flags = usb_retimers[port].i2c_addr_flags; - const int gpio_enable = usb_retimers[port].gpio_enable; - const int gpio_dp_enable = usb_retimers[port].gpio_dp_enable; - - /* USB */ - if (mux_state & MUX_USB_ENABLED) { - gpio_or_ioex_set_level(gpio_enable, 1); - /* USB with DP */ - if (mux_state & MUX_DP_ENABLED) { - gpio_or_ioex_set_level(gpio_dp_enable, 1); - mode_val |= (mux_state & MUX_POLARITY_INVERTED) - ? PI3DPX1207_MODE_CONF_USB_DP_FLIP - : PI3DPX1207_MODE_CONF_USB_DP; - } - /* USB without DP */ - else { - gpio_or_ioex_set_level(gpio_dp_enable, 0); - mode_val |= (mux_state & MUX_POLARITY_INVERTED) - ? PI3DPX1207_MODE_CONF_USB_FLIP - : PI3DPX1207_MODE_CONF_USB; - } - } - /* DP without USB */ - else if (mux_state & MUX_DP_ENABLED) { - gpio_or_ioex_set_level(gpio_enable, 1); - gpio_or_ioex_set_level(gpio_dp_enable, 1); - mode_val |= (mux_state & MUX_POLARITY_INVERTED) - ? PI3DPX1207_MODE_CONF_DP_FLIP - : PI3DPX1207_MODE_CONF_DP; - } - /* Nothing enabled, power down the retimer */ - else { - pi3dpx1207_shutoff_power(port); - return EC_SUCCESS; - } - - /* Write the retimer config byte */ - rv = pi3dpx1207_i2c_write(i2c_port, i2c_addr_flags, - PI3DPX1207_MODE_OFFSET, - mode_val); - return rv; -} - -const struct usb_retimer_driver pi3dpx1207_usb_retimer = { - .init = pi3dpx1207_init, - .set = pi3dpx1207_set_mux, - .enter_low_power_mode = pi3dpx1207_enter_low_power_mode, -}; diff --git a/driver/retimer/pi3dpx1207.h b/driver/retimer/pi3dpx1207.h deleted file mode 100644 index 7b3c3047f2..0000000000 --- a/driver/retimer/pi3dpx1207.h +++ /dev/null @@ -1,44 +0,0 @@ -/* Copyright 2019 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. - * - * PI3DPX1207 retimer. - */ - -#ifndef __CROS_EC_USB_RETIMER_PI3PDX1207_H -#define __CROS_EC_USB_RETIMER_PI3PDX1207_H - -#define PI3DPX1207_I2C_ADDR_FLAGS 0x57 -#define PI3DPX1207_NUM_REGISTERS 32 - -/* Register Offset 0 - Revision and Vendor ID */ -#define PI3DPX1207_VID_OFFSET 0 - -#define PI3DPX1207B_VID 0x03 -#define PI3DPX1207C_VID 0x13 - -/* Register Offset 1 - Device Type/ID */ -#define PI3DPX1207_DID_OFFSET 1 - -#define PI3DPX1207_DID_ACTIVE_MUX 0x11 - -/* Register Offset 3 - Mode Control */ -#define PI3DPX1207_MODE_OFFSET 3 - -#define PI3DPX1207_MODE_WATCHDOG_EN 0x02 - -#define PI3DPX1207B_MODE_GEN_APP_EN 0x08 - -#define PI3DPX1207_MODE_CONF_SAFE 0x00 -#define PI3DPX1207_MODE_CONF_DP 0x20 -#define PI3DPX1207_MODE_CONF_DP_FLIP 0x30 -#define PI3DPX1207_MODE_CONF_USB 0x40 -#define PI3DPX1207_MODE_CONF_USB_FLIP 0x50 -#define PI3DPX1207_MODE_CONF_USB_DP 0x60 -#define PI3DPX1207_MODE_CONF_USB_DP_FLIP 0x70 -#define PI3DPX1207_MODE_CONF_USB_SUPER 0xC0 - -/* Supported USB retimer drivers */ -extern const struct usb_retimer_driver pi3dpx1207_usb_retimer; - -#endif /* __CROS_EC_USB_RETIMER_PI3PDX1207_H */ diff --git a/driver/sensorhub_lsm6dsm.c b/driver/sensorhub_lsm6dsm.c deleted file mode 100644 index 37072d5970..0000000000 --- a/driver/sensorhub_lsm6dsm.c +++ /dev/null @@ -1,327 +0,0 @@ -/* Copyright 2018 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. - */ - -/* - * Sensor Hub Driver for LSM6DSM acce/gyro module to enable connecting - * external sensors like magnetometer - */ - -#include "console.h" -#include "driver/accelgyro_lsm6dsm.h" -#include "driver/sensorhub_lsm6dsm.h" -#include "driver/stm_mems_common.h" - -#define CPRINTF(format, args...) cprintf(CC_ACCEL, format, ## args) - -static int set_reg_bit_field(const struct motion_sensor_t *s, - uint8_t reg, uint8_t bit_field) -{ - int tmp; - int ret; - - ret = st_raw_read8(s->port, s->i2c_spi_addr_flags, reg, &tmp); - if (ret != EC_SUCCESS) - return ret; - - tmp |= bit_field; - return st_raw_write8(s->port, s->i2c_spi_addr_flags, reg, tmp); -} - -static int clear_reg_bit_field(const struct motion_sensor_t *s, - uint8_t reg, uint8_t bit_field) -{ - int tmp; - int ret; - - ret = st_raw_read8(s->port, s->i2c_spi_addr_flags, reg, &tmp); - if (ret != EC_SUCCESS) - return ret; - - tmp &= ~(bit_field); - return st_raw_write8(s->port, s->i2c_spi_addr_flags, reg, tmp); -} - -static inline int enable_sensorhub_func(const struct motion_sensor_t *s) -{ - return set_reg_bit_field(s, LSM6DSM_CTRL10_ADDR, - LSM6DSM_EMBED_FUNC_EN); -} - -static inline int disable_sensorhub_func(const struct motion_sensor_t *s) -{ - return clear_reg_bit_field(s, LSM6DSM_CTRL10_ADDR, - LSM6DSM_EMBED_FUNC_EN); -} - -/* - * Sensor hub includes embedded register banks associated with external - * sensors. 4 external sensor slaves can be attached to the sensor hub - * and hence 4 such register banks exist. The access to them are disabled - * by default. Below 2 helper functions help enable/disable access to those - * register banks. - */ -static inline int enable_ereg_bank_acc(const struct motion_sensor_t *s) -{ - return set_reg_bit_field(s, LSM6DSM_FUNC_CFG_ACC_ADDR, - LSM6DSM_FUNC_CFG_EN); -} - -static inline int disable_ereg_bank_acc(const struct motion_sensor_t *s) -{ - return clear_reg_bit_field(s, LSM6DSM_FUNC_CFG_ACC_ADDR, - LSM6DSM_FUNC_CFG_EN); -} - -static inline int enable_aux_i2c_master(const struct motion_sensor_t *s) -{ - return set_reg_bit_field(s, LSM6DSM_MASTER_CFG_ADDR, - LSM6DSM_I2C_MASTER_ON); -} - -static inline int disable_aux_i2c_master(const struct motion_sensor_t *s) -{ - return clear_reg_bit_field(s, LSM6DSM_MASTER_CFG_ADDR, - LSM6DSM_I2C_MASTER_ON); -} - -static inline int restore_master_cfg(const struct motion_sensor_t *s, - int cache) -{ - return st_raw_write8(s->port, s->i2c_spi_addr_flags, - LSM6DSM_MASTER_CFG_ADDR, cache); -} - -static int enable_i2c_pass_through(const struct motion_sensor_t *s, - int *cache) -{ - int ret; - - ret = st_raw_read8(s->port, s->i2c_spi_addr_flags, - LSM6DSM_MASTER_CFG_ADDR, cache); - if (ret != EC_SUCCESS) { - CPRINTF("%s: %s type:0x%x MCR error ret: %d\n", - __func__, s->name, s->type, ret); - return ret; - } - - /* - * Fake set sensor hub to external trigger event and wait for 10ms. - * Wait is for any pending bus activity(probably read) to settle down - * so that there is no bus contention. - */ - ret = st_raw_write8(s->port, s->i2c_spi_addr_flags, - LSM6DSM_MASTER_CFG_ADDR, - *cache | LSM6DSM_EXT_TRIGGER_EN); - if (ret != EC_SUCCESS) { - CPRINTF("%s: %s type:0x%x MCETEN error ret: %d\n", - __func__, s->name, s->type, ret); - return ret; - } - msleep(10); - - ret = st_raw_write8(s->port, s->i2c_spi_addr_flags, - LSM6DSM_MASTER_CFG_ADDR, - *cache & ~(LSM6DSM_EXT_TRIGGER_EN - | LSM6DSM_I2C_MASTER_ON)); - if (ret != EC_SUCCESS) { - CPRINTF("%s: %s type:0x%x MCC error ret: %d\n", - __func__, s->name, s->type, ret); - restore_master_cfg(s, *cache); - return ret; - } - - return st_raw_write8(s->port, s->i2c_spi_addr_flags, - LSM6DSM_MASTER_CFG_ADDR, LSM6DSM_I2C_PASS_THRU_MODE); -} - -static inline int power_down_accel(const struct motion_sensor_t *s, - int *cache) -{ - int ret; - - ret = st_raw_read8(s->port, s->i2c_spi_addr_flags, - LSM6DSM_CTRL1_ADDR, cache); - if (ret != EC_SUCCESS) { - CPRINTF("%s: %s type:0x%x CTRL1R error ret: %d\n", - __func__, s->name, s->type, ret); - return ret; - } - - return st_raw_write8(s->port, s->i2c_spi_addr_flags, - LSM6DSM_CTRL1_ADDR, - *cache & ~LSM6DSM_XL_ODR_MASK); -} - -static inline int restore_ctrl1(const struct motion_sensor_t *s, int cache) -{ - return st_raw_write8(s->port, s->i2c_spi_addr_flags, - LSM6DSM_CTRL1_ADDR, cache); -} - -static int config_slv0_read(const struct motion_sensor_t *s, - const uint16_t slv_addr_flags, - uint16_t reg, uint8_t len) -{ - int ret; - uint16_t addr_8bit = I2C_GET_ADDR(slv_addr_flags) << 1; - - ret = st_raw_write8(s->port, s->i2c_spi_addr_flags, - LSM6DSM_SLV0_ADD_ADDR, - (addr_8bit | LSM6DSM_SLV0_RD_BIT)); - if (ret != EC_SUCCESS) { - CPRINTF("%s: %s type:0x%x SA error ret: %d\n", - __func__, s->name, s->type, ret); - return ret; - } - - ret = st_raw_write8(s->port, s->i2c_spi_addr_flags, - LSM6DSM_SLV0_SUBADD_ADDR, reg); - if (ret != EC_SUCCESS) { - CPRINTF("%s: %s type:0x%x RA error ret: %d\n", - __func__, s->name, s->type, ret); - return ret; - } - - /* - * No decimation for external sensor 0, - * Number of sensors connected to external sensor hub 1 - */ - ret = st_raw_write8(s->port, s->i2c_spi_addr_flags, - LSM6DSM_SLV0_CONFIG_ADDR, - (len & LSM6DSM_SLV0_NUM_OPS_MASK)); - if (ret != EC_SUCCESS) { - CPRINTF("%s: %s type:0x%x CFG error ret: %d\n", - __func__, s->name, s->type, ret); - return ret; - } - - return EC_SUCCESS; -} - -int sensorhub_config_ext_reg(const struct motion_sensor_t *s, - const uint16_t slv_addr_flags, - uint8_t reg, uint8_t val) -{ - int ret; - int tmp; - - ret = enable_i2c_pass_through(s, &tmp); - if (ret != EC_SUCCESS) { - CPRINTF("%s: %s type:0x%x ENI2C error ret: %d\n", - __func__, s->name, s->type, ret); - return ret; - } - - ret = st_raw_write8(s->port, slv_addr_flags, reg, val); - restore_master_cfg(s, tmp); - return ret; -} - -int sensorhub_config_slv0_read(const struct motion_sensor_t *s, - uint16_t slv_addr_flags, uint8_t reg, int len) -{ - int tmp_xl_cfg; - int ret; - - if (len <= 0 || len > OUT_XYZ_SIZE) { - CPRINTF("%s: %s type:0x%x Invalid length: %d\n", - __func__, s->name, s->type, len); - return EC_ERROR_INVAL; - } - - ret = power_down_accel(s, &tmp_xl_cfg); - if (ret != EC_SUCCESS) { - CPRINTF("%s: %s type:0x%x PDXL error ret: %d\n", - __func__, s->name, s->type, ret); - return ret; - } - - ret = enable_ereg_bank_acc(s); - if (ret != EC_SUCCESS) { - CPRINTF("%s: %s type:0x%x ENERB error ret: %d\n", - __func__, s->name, s->type, ret); - goto out_restore_ctrl1; - } - - ret = config_slv0_read(s, slv_addr_flags, reg, len); - disable_ereg_bank_acc(s); - if (ret != EC_SUCCESS) { - CPRINTF("%s: %s type:0x%x CS0R error ret: %d\n", - __func__, s->name, s->type, ret); - goto out_restore_ctrl1; - } - - ret = enable_sensorhub_func(s); - if (ret != EC_SUCCESS) { - CPRINTF("%s: %s type:0x%x ENSH error ret: %d\n", - __func__, s->name, s->type, ret); - goto out_restore_ctrl1; - } - - ret = enable_aux_i2c_master(s); - if (ret != EC_SUCCESS) { - CPRINTF("%s: %s type:0x%x ENI2CM error ret: %d\n", - __func__, s->name, s->type, ret); - disable_sensorhub_func(s); - } -out_restore_ctrl1: - restore_ctrl1(s, tmp_xl_cfg); - return ret; -} - -int sensorhub_slv0_data_read(const struct motion_sensor_t *s, uint8_t *raw) -{ - int ret; - - /* - * Accel/Gyro is already reading slave 0 data into the sensorhub1 - * register as soon as the accel is in power-up mode. So return the - * contents of that register. - */ - ret = st_raw_read_n_noinc(s->port, s->i2c_spi_addr_flags, - LSM6DSM_SENSORHUB1_REG, - raw, OUT_XYZ_SIZE); - if (ret != EC_SUCCESS) { - CPRINTF("%s: %s type:0x%x SH1R error ret: %d\n", - __func__, s->name, s->type, ret); - return ret; - } - return EC_SUCCESS; -} - -int sensorhub_check_and_rst(const struct motion_sensor_t *s, - const uint16_t slv_addr_flags, - uint8_t whoami_reg, uint8_t whoami_val, - uint8_t rst_reg, uint8_t rst_val) -{ - int ret, tmp; - int tmp_master_cfg; - - ret = enable_i2c_pass_through(s, &tmp_master_cfg); - if (ret != EC_SUCCESS) { - CPRINTF("%s: %s type:0x%x ENI2C error ret: %d\n", - __func__, s->name, s->type, ret); - return ret; - } - - ret = st_raw_read8(s->port, slv_addr_flags, whoami_reg, &tmp); - if (ret != EC_SUCCESS) { - CPRINTF("%s: %s type:0x%x WAIR error ret: %d\n", - __func__, s->name, s->type, ret); - goto err_restore_master_cfg; - } - - if (tmp != whoami_val) { - CPRINTF("%s: %s type:0x%x WAIC error ret: %d\n", - __func__, s->name, s->type, ret); - ret = EC_ERROR_UNKNOWN; - goto err_restore_master_cfg; - } - - ret = st_raw_write8(s->port, slv_addr_flags, rst_reg, rst_val); -err_restore_master_cfg: - restore_master_cfg(s, tmp_master_cfg); - return ret; -} diff --git a/driver/sensorhub_lsm6dsm.h b/driver/sensorhub_lsm6dsm.h deleted file mode 100644 index 07b19046df..0000000000 --- a/driver/sensorhub_lsm6dsm.h +++ /dev/null @@ -1,71 +0,0 @@ -/* Copyright 2018 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. - */ - -/* - * LSM6DSM Sensor Hub driver to enable interfacing with external sensors - * like magnetometer for Chrome EC - */ - -#ifndef __CROS_EC_SENSORHUB_LSM6DSM_H -#define __CROS_EC_SENSORHUB_LSM6DSM_H - -#include "common.h" -#include "motion_sense.h" - -/** - * Configure the register of an external sensor that is attached to sensor - * hub with a specific value. - * - * @param s Pointer to external motion sensor's data structure. - * @param slv_addr I2C Slave Address of the external sensor. - * @param reg Register Address to write within the external sensor. - * @param val Value to be written into the external sensor register. - * @return EC_SUCCESS on success, EC error codes on failure. - */ -int sensorhub_config_ext_reg(const struct motion_sensor_t *s, - const uint16_t slv_addr_flags, - uint8_t reg, uint8_t val); - -/** - * Configure the sensor hub to read data from a specific register of an - * external sensor that is attached to it. - * - * @param s Pointer to external motion sensor's data structure. - * @param slv_addr I2C Slave Address of the external sensor. - * @param reg Register Address to read from the external sensor. - * @param len Length of data to be read. - * @return EC_SUCCESS on success, EC error codes on failure. - */ -int sensorhub_config_slv0_read(const struct motion_sensor_t *s, - const uint16_t slv_addr_flags, - uint8_t reg, int len); - -/** - * Reads the data from the register bank that is associated with the slave0 - * of the sensor hub. - * - * @param s Pointer to external motion sensor's data structure. - * @param raw Vector to hold the data from the external sensor. - * @return EC_SUCCESS on success, EC error codes on failure. - */ -int sensorhub_slv0_data_read(const struct motion_sensor_t *s, uint8_t *raw); - -/** - * Check the identity of the external sensor and then reset the external - * sensor that is attached to the sensor hub. - * - * @param s Pointer to external motion sensor's data structure. - * @param slv_addr I2C Slave Address of the external sensor. - * @param whoami_reg Register address to identify the sensor. - * @param whoami_val Expected value to be read from the whoami_reg. - * @param rst_reg Register address to reset the external sensor. - * @param rst_val Value to be written to the reset register. - * @return EC_SUCCESS on success, EC error codes on failure. - */ -int sensorhub_check_and_rst(const struct motion_sensor_t *s, - const uint16_t slv_addr_flags, - uint8_t whoami_reg, uint8_t whoami_val, - uint8_t rst_reg, uint8_t rst_val); -#endif /* __CROS_EC_SENSORHUB_LSM6DSM_H */ diff --git a/driver/stm_mems_common.c b/driver/stm_mems_common.c deleted file mode 100644 index 6cee29977d..0000000000 --- a/driver/stm_mems_common.c +++ /dev/null @@ -1,146 +0,0 @@ -/* 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" - -/** - * st_raw_read_n - Read n bytes for read - */ -int st_raw_read_n(const int port, - const uint16_t i2c_addr_flags, - const uint8_t reg, uint8_t *data_ptr, const int len) -{ - /* TODO: Implement SPI interface support */ - return i2c_read_block(port, i2c_addr_flags, - reg | 0x80, data_ptr, len); -} - -/** - * st_raw_read_n_noinc - Read n bytes for read (no auto inc address) - */ -int st_raw_read_n_noinc(const int port, - const uint16_t i2c_addr_flags, - const uint8_t reg, uint8_t *data_ptr, const int len) -{ - /* TODO: Implement SPI interface support */ - return i2c_read_block(port, i2c_addr_flags, - reg, data_ptr, len); -} - - /** - * 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 = st_raw_read8(s->port, s->i2c_spi_addr_flags, - 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 st_raw_write8(s->port, s->i2c_spi_addr_flags, - 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, intv3_t v, uint8_t *data) -{ - int i, range; - struct stprivate_data *drvdata = s->drv_data; - /* - * Data is left-aligned and the bottom bits need to be - * cleared because they may contain trash data. - */ - uint16_t mask = ~((1 << (16 - drvdata->resol)) - 1); - - for (i = X; i <= Z; i++) { - v[i] = ((data[i * 2 + 1] << 8) | data[i * 2]) & mask; - } - - 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; -} diff --git a/driver/stm_mems_common.h b/driver/stm_mems_common.h deleted file mode 100644 index 1984e5e070..0000000000 --- a/driver/stm_mems_common.h +++ /dev/null @@ -1,125 +0,0 @@ -/* 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 oin Chrome EC */ - -#ifndef __CROS_EC_ST_COMMONS_H -#define __CROS_EC_ST_COMMONS_H - -#include "common.h" -#include "util.h" -#include "accelgyro.h" -#include "console.h" -#include "i2c.h" - -/* X, Y, Z axis data len */ -#define OUT_XYZ_SIZE 6 - -#define ST_NORMALIZE_RATE(_fs) (1 << __fls(_fs)) - -#ifdef CONFIG_ACCEL_FIFO -#define FIFO_BUFFER_NUM_PATTERN 32 -/* Define number of data to be read from FIFO each time - * It must be a multiple of OUT_XYZ_SIZE. - * In case of LSM6DSM FIFO contains pattern depending ODR - * of Acc/gyro, be sure that FIFO can contains almost - * FIFO_BUFFER_NUM_PATTERNpattern - */ -#define FIFO_READ_LEN (FIFO_BUFFER_NUM_PATTERN * OUT_XYZ_SIZE) - -#endif /* CONFIG_ACCEL_FIFO */ - -/** - * Read single register - */ -static inline int st_raw_read8(const int port, - const uint16_t i2c_spi_addr_flags, - const int reg, int *data_ptr) -{ - /* TODO: Implement SPI interface support */ - return i2c_read8(port, i2c_spi_addr_flags, reg, data_ptr); -} - -/** - * Write single register - */ -static inline int st_raw_write8(const int port, - const uint16_t i2c_spi_addr_flags, - const int reg, int data) -{ - /* TODO: Implement SPI interface support */ - return i2c_write8(port, i2c_spi_addr_flags, reg, data); -} - -/** - * st_raw_read_n - Read n bytes for read - */ -int st_raw_read_n(const int port, - const uint16_t i2c_spi_addr_flags, - const uint8_t reg, uint8_t *data_ptr, const int len); - -/** - * st_raw_read_n_noinc - Read n bytes for read (no auto inc address) - */ -int st_raw_read_n_noinc(const int port, - const uint16_t i2c_spi_addr_flags, - const uint8_t reg, uint8_t *data_ptr, const int len); - - /** - * 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); - - /** - * st_get_resolution - Get bit resolution - * @s: Motion sensor pointer - */ -int st_get_resolution(const struct motion_sensor_t *s); - -/** - * 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); - -/** - * 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); - -/** - * st_get_data_rate - Get data rate (ODR) - * @s: Motion sensor pointer - */ -int st_get_data_rate(const struct motion_sensor_t *s); - -/** - * st_normalize - Apply to LSB data sensitivity and rotation - * @s: Motion sensor pointer - * @v: vector - * @data: LSB raw data - */ -void st_normalize(const struct motion_sensor_t *s, intv3_t v, uint8_t *data); - -/* Internal data structure for sensors */ -struct stprivate_data { - struct accelgyro_saved_data_t base; - int16_t offset[3]; - uint8_t resol; -}; - -#endif /* __CROS_EC_ST_COMMONS_H */ diff --git a/driver/temp_sensor/adt7481.c b/driver/temp_sensor/adt7481.c deleted file mode 100644 index cbd32e5cd5..0000000000 --- a/driver/temp_sensor/adt7481.c +++ /dev/null @@ -1,352 +0,0 @@ -/* Copyright 2017 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. - */ - -/* ADT7481 temperature sensor module for Chrome EC */ - -#include "common.h" -#include "console.h" -#include "adt7481.h" -#include "gpio.h" -#include "i2c.h" -#include "hooks.h" -#include "util.h" - -static int temp_val_local; -static int temp_val_remote1; -static int temp_val_remote2; -static uint8_t is_sensor_shutdown; - -/** - * Determine whether the sensor is powered. - * - * @return non-zero the adt7481 sensor is powered. - */ -static int has_power(void) -{ -#ifdef CONFIG_TEMP_SENSOR_POWER_GPIO - return gpio_get_level(CONFIG_TEMP_SENSOR_POWER_GPIO); -#else - return !is_sensor_shutdown; -#endif -} - -static int raw_read8(const int offset, int *data_ptr) -{ - return i2c_read8(I2C_PORT_THERMAL, ADT7481_I2C_ADDR_FLAGS, - offset, data_ptr); -} - -static int raw_write8(const int offset, int data) -{ - return i2c_write8(I2C_PORT_THERMAL, ADT7481_I2C_ADDR_FLAGS, - offset, data); -} - -static int get_temp(const int offset, int *temp_ptr) -{ - int rv; - int temp_raw = 0; - - rv = raw_read8(offset, &temp_raw); - if (rv < 0) - return rv; - - *temp_ptr = (int)(int8_t)temp_raw; - return EC_SUCCESS; -} - -#ifdef CONFIG_CMD_TEMP_SENSOR -static int adt7481_set_temp(const int offset, int temp) -{ - if (temp < -127 || temp > 127) - return EC_ERROR_INVAL; - - return raw_write8(offset, (uint8_t)temp); -} -#endif - -int adt7481_get_val(int idx, int *temp_ptr) -{ - if (!has_power()) - return EC_ERROR_NOT_POWERED; - - switch (idx) { - case ADT7481_IDX_LOCAL: - *temp_ptr = temp_val_local; - break; - case ADT7481_IDX_REMOTE1: - *temp_ptr = temp_val_remote1; - break; - case ADT7481_IDX_REMOTE2: - *temp_ptr = temp_val_remote2; - break; - default: - return EC_ERROR_UNKNOWN; - } - - return EC_SUCCESS; -} - -static int adt7481_shutdown(uint8_t want_shutdown) -{ - int ret, value; - - if (want_shutdown == is_sensor_shutdown) - return EC_SUCCESS; - - ret = raw_read8(ADT7481_CONFIGURATION1_R, &value); - if (ret < 0) { - ccprintf("ERROR: Temp sensor I2C read8 error.\n"); - return ret; - } - - if (want_shutdown && !(value & ADT7481_CONFIG1_RUN_L)) { - /* adt7481 is running, and want it to shutdown */ - /* CONFIG REG1 BIT6: 0=Run, 1=Shutdown */ - /* shut it down */ - value |= ADT7481_CONFIG1_RUN_L; - ret = raw_write8(ADT7481_CONFIGURATION1_R, value); - } else if (!want_shutdown && (value & ADT7481_CONFIG1_RUN_L)) { - /* adt7481 is shutdown, and want turn it on */ - value &= ~ADT7481_CONFIG1_RUN_L; - ret = raw_write8(ADT7481_CONFIGURATION1_R, value); - } - /* else, the current setting is exactly what you want */ - - is_sensor_shutdown = want_shutdown; - return ret; -} - -static int adt7481_set_therm_mode(void) -{ - int ret = 0; - int data = 0; - - ret = raw_read8(ADT7481_CONFIGURATION1_R, &data); - if (ret) - return EC_ERROR_UNKNOWN; - - data |= ADT7481_CONFIG1_MODE; - ret = raw_write8(ADT7481_CONFIGURATION1_W, data); - if (ret) - return EC_ERROR_UNKNOWN; - - return EC_SUCCESS; -} - -int adt7481_set_therm_limit(int channel, int limit_c, int hysteresis) -{ - int ret = 0; - int reg = 0; - - if (channel >= ADT7481_CHANNEL_COUNT) - return EC_ERROR_INVAL; - - if (hysteresis > ADT7481_HYSTERESIS_HIGH_LIMIT || - hysteresis < ADT7481_HYSTERESIS_LOW_LIMIT) - return EC_ERROR_INVAL; - - /* hysteresis must be less than high limit */ - if (hysteresis > limit_c) - return EC_ERROR_INVAL; - - if (adt7481_set_therm_mode() != EC_SUCCESS) - return EC_ERROR_UNKNOWN; - - switch (channel) { - case ADT7481_CHANNEL_LOCAL: - reg = ADT7481_LOCAL_HIGH_LIMIT_W; - break; - case ADT7481_CHANNEL_REMOTE1: - reg = ADT7481_REMOTE1_HIGH_LIMIT_W; - break; - case ADT7481_CHANNEL_REMOTE2: - reg = ADT7481_REMOTE2_HIGH_LIMIT; - break; - } - - ret = raw_write8(reg, limit_c); - if (ret) - return EC_ERROR_UNKNOWN; - - ret = raw_write8(ADT7481_THERM_HYSTERESIS, hysteresis); - if (ret) - return EC_ERROR_UNKNOWN; - - return EC_SUCCESS; -} - -static void adt7481_temp_sensor_poll(void) -{ - int temp_c; - - if (!has_power()) - return; - - if (get_temp(ADT7481_LOCAL, &temp_c) == EC_SUCCESS) - temp_val_local = C_TO_K(temp_c); - - if (get_temp(ADT7481_REMOTE1, &temp_c) == EC_SUCCESS) - temp_val_remote1 = C_TO_K(temp_c); - - if (get_temp(ADT7481_REMOTE2, &temp_c) == EC_SUCCESS) - temp_val_remote2 = C_TO_K(temp_c); -} -DECLARE_HOOK(HOOK_SECOND, adt7481_temp_sensor_poll, HOOK_PRIO_TEMP_SENSOR); - -#ifdef CONFIG_CMD_TEMP_SENSOR -static void print_temps( - const char *name, - const int adt7481_temp_reg, - const int adt7481_therm_limit_reg, - const int adt7481_high_limit_reg, - const int adt7481_low_limit_reg) -{ - int value; - - if (!has_power()) { - ccprintf(" ADT7481 is shutdown\n"); - return; - } - - ccprintf("%s:\n", name); - - if (get_temp(adt7481_temp_reg, &value) == EC_SUCCESS) - ccprintf(" Temp %3dC\n", value); - - if (get_temp(adt7481_therm_limit_reg, &value) == EC_SUCCESS) - ccprintf(" Therm Trip %3dC\n", value); - - if (get_temp(adt7481_high_limit_reg, &value) == EC_SUCCESS) - ccprintf(" High Alarm %3dC\n", value); - - if (get_temp(adt7481_low_limit_reg, &value) == EC_SUCCESS) - ccprintf(" Low Alarm %3dC\n", value); -} - -static int print_status(void) -{ - int value; - - print_temps("Local", ADT7481_LOCAL, - ADT7481_LOCAL_THERM_LIMIT, - ADT7481_LOCAL_HIGH_LIMIT_R, - ADT7481_LOCAL_LOW_LIMIT_R); - - print_temps("Remote1", ADT7481_REMOTE1, - ADT7481_REMOTE1_THERM_LIMIT, - ADT7481_REMOTE1_HIGH_LIMIT_R, - ADT7481_REMOTE1_LOW_LIMIT_R); - - print_temps("Remote2", ADT7481_REMOTE2, - ADT7481_REMOTE2_THERM_LIMIT, - ADT7481_REMOTE2_HIGH_LIMIT, - ADT7481_REMOTE2_LOW_LIMIT); - - ccprintf("\n"); - - if (raw_read8(ADT7481_STATUS1_R, &value) == EC_SUCCESS) - ccprintf("STATUS1: %pb\n", BINARY_VALUE(value, 8)); - - if (raw_read8(ADT7481_STATUS2_R, &value) == EC_SUCCESS) - ccprintf("STATUS2: %pb\n", BINARY_VALUE(value, 8)); - - if (raw_read8(ADT7481_CONFIGURATION1_R, &value) == EC_SUCCESS) - ccprintf("CONFIG1: %pb\n", BINARY_VALUE(value, 8)); - - if (raw_read8(ADT7481_CONFIGURATION2, &value) == EC_SUCCESS) - ccprintf("CONFIG2: %pb\n", BINARY_VALUE(value, 8)); - - return EC_SUCCESS; -} - -static int command_adt7481(int argc, char **argv) -{ - char *command; - char *e; - char *power; - int data; - int offset; - int rv; - - /* handle "power" command before checking the power status. */ - if ((argc == 3) && !strcasecmp(argv[1], "power")) { - power = argv[2]; - if (!strncasecmp(power, "on", sizeof("on"))) { - rv = adt7481_set_power(ADT7481_POWER_ON); - if (!rv) - print_status(); - } else if (!strncasecmp(power, "off", sizeof("off"))) - rv = adt7481_set_power(ADT7481_POWER_OFF); - else - return EC_ERROR_PARAM2; - ccprintf("Set ADT7481 %s\n", power); - return rv; - } - - if (!has_power()) { - ccprintf("ERROR: Temp sensor not powered.\n"); - return EC_ERROR_NOT_POWERED; - } - - /* If no args just print status */ - if (argc == 1) - return print_status(); - - if (argc < 3) - return EC_ERROR_PARAM_COUNT; - - command = argv[1]; - offset = strtoi(argv[2], &e, 0); - if (*e || offset < 0 || offset > 255) - return EC_ERROR_PARAM2; - - if (!strcasecmp(command, "getbyte")) { - rv = raw_read8(offset, &data); - if (rv < 0) - return rv; - ccprintf("Byte at offset 0x%02x is %pb\n", - offset, BINARY_VALUE(data, 8)); - return rv; - } - - /* Remaining commands are "adt7481 set-command offset data" */ - if (argc != 4) - return EC_ERROR_PARAM_COUNT; - - data = strtoi(argv[3], &e, 0); - if (*e) - return EC_ERROR_PARAM3; - - if (!strcasecmp(command, "settemp")) { - ccprintf("Setting 0x%02x to %dC\n", offset, data); - rv = adt7481_set_temp(offset, data); - } else if (!strcasecmp(command, "setbyte")) { - ccprintf("Setting 0x%02x to 0x%02x\n", offset, data); - rv = raw_write8(offset, data); - } else - return EC_ERROR_PARAM1; - - return rv; -} -DECLARE_CONSOLE_COMMAND(adt7481, command_adt7481, - "[settemp|setbyte <offset> <value>] or [getbyte <offset>] or" - "[power <on|off>]. " - "Temps in Celsius.", - "Print tmp432 temp sensor status or set parameters."); -#endif - -int adt7481_set_power(enum adt7481_power_state power_on) -{ -#ifndef CONFIG_TEMP_SENSOR_POWER_GPIO - uint8_t shutdown = (power_on == ADT7481_POWER_OFF) ? 1 : 0; - - return adt7481_shutdown(shutdown); -#else - gpio_set_level(CONFIG_TEMP_SENSOR_POWER_GPIO, power_on); - return EC_SUCCESS; -#endif -} - diff --git a/driver/temp_sensor/adt7481.h b/driver/temp_sensor/adt7481.h deleted file mode 100644 index 78541a0a3b..0000000000 --- a/driver/temp_sensor/adt7481.h +++ /dev/null @@ -1,178 +0,0 @@ -/* Copyright 2017 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. - */ - -/* ADT7481 temperature sensor module for Chrome EC */ - -#ifndef __CROS_EC_ADT7481_H -#define __CROS_EC_ADT7481_H - -#define ADT7481_I2C_ADDR_FLAGS 0x4B - -#define ADT7481_IDX_LOCAL 0 -#define ADT7481_IDX_REMOTE1 1 -#define ADT7481_IDX_REMOTE2 2 - -/* Chip-specific registers */ -#define ADT7481_LOCAL 0x00 -#define ADT7481_REMOTE1 0x01 -#define ADT7481_STATUS1_R 0x02 -#define ADT7481_CONFIGURATION1_R 0x03 -#define ADT7481_CONVERSION_RATE_R 0x04 -#define ADT7481_LOCAL_HIGH_LIMIT_R 0x05 -#define ADT7481_LOCAL_LOW_LIMIT_R 0x06 -#define ADT7481_REMOTE1_HIGH_LIMIT_R 0x07 -#define ADT7481_REMOTE1_LOW_LIMIT_R 0x08 -#define ADT7481_CONFIGURATION1_W 0x09 -#define ADT7481_CONVERSION_RATE_W 0x0a -#define ADT7481_LOCAL_HIGH_LIMIT_W 0x0b -#define ADT7481_LOCAL_LOW_LIMIT_W 0x0c -#define ADT7481_REMOTE1_HIGH_LIMIT_W 0x0d -#define ADT7481_REMOTE1_LOW_LIMIT_W 0x0e -#define ADT7481_ONESHOT_W 0x0f -#define ADT7481_REMOTE1_EXTD_R 0x10 -#define ADT7481_REMOTE1_OFFSET 0x11 -#define ADT7481_REMOTE1_OFFSET_EXTD 0x12 -#define ADT7481_REMOTE1_HIGH_LIMIT_EXTD 0x13 -#define ADT7481_REMOTE1_LOW_LIMIT_EXTD 0x14 -#define ADT7481_REMOTE1_THERM_LIMIT 0x19 -#define ADT7481_LOCAL_THERM_LIMIT 0x20 -#define ADT7481_THERM_HYSTERESIS 0x21 -#define ADT7481_CONSECUTIVE_ALERT 0x22 -#define ADT7481_STATUS2_R 0x23 -#define ADT7481_CONFIGURATION2 0x24 -#define ADT7481_REMOTE2 0x30 -#define ADT7481_REMOTE2_HIGH_LIMIT 0x31 -#define ADT7481_REMOTE2_LOW_LIMIT 0x32 -#define ADT7481_REMOTE2_EXTD_R 0x33 -#define ADT7481_REMOTE2_OFFSET 0x34 -#define ADT7481_REMOTE2_OFFSET_EXTD 0x35 -#define ADT7481_REMOTE2_HIGH_LIMIT_EXTD 0x36 -#define ADT7481_REMOTE2_LOW_LIMIT_EXTD 0x37 -#define ADT7481_REMOTE2_THERM_LIMIT 0x39 -#define ADT7481_DEVICE_ID 0x3d -#define ADT7481_MANUFACTURER_ID 0x3e - -/* Config1 register bits */ -#define ADT7481_CONFIG1_REMOTE1_ALERT_MASK BIT(0) -#define ADT7481_CONFIG1_REMOTE2_ALERT_MASK BIT(1) -#define ADT7481_CONFIG1_TEMP_RANGE BIT(2) -#define ADT7481_CONFIG1_SEL_REMOTE2 BIT(3) -/* ADT7481_CONFIG1_MODE bit is use to enable THERM mode */ -#define ADT7481_CONFIG1_MODE BIT(5) -#define ADT7481_CONFIG1_RUN_L BIT(6) -/* mask all alerts on ALERT# pin */ -#define ADT7481_CONFIG1_ALERT_MASK_L BIT(7) - -/* Config2 register bits */ -#define ADT7481_CONFIG2_LOCK BIT(7) - -/* Conversion Rate/Channel Select Register */ -#define ADT7481_CONV_RATE_MASK (0x0f) -#define ADT7481_CONV_RATE_16S (0x00) -#define ADT7481_CONV_RATE_8S (0x01) -#define ADT7481_CONV_RATE_4S (0x02) -#define ADT7481_CONV_RATE_2S (0x03) -#define ADT7481_CONV_RATE_1S (0x04) -#define ADT7481_CONV_RATE_500MS (0x05) -#define ADT7481_CONV_RATE_250MS (0x06) -#define ADT7481_CONV_RATE_125MS (0x07) -#define ADT7481_CONV_RATE_62500US (0x08) -#define ADT7481_CONV_RATE_31250US (0x09) -#define ADT7481_CONV_RATE_15500US (0x0a) -/* continuous mode 73 ms averaging */ -#define ADT7481_CONV_RATE_73MS_AVE (0x0b) -#define ADT7481_CONV_CHAN_SELECT_MASK (0x30) -#define ADT7481_CONV_CHAN_SEL_ROUND_ROBIN (0 << 4) -#define ADT7481_CONV_CHAN_SEL_LOCAL BIT(4) -#define ADT7481_CONV_CHAN_SEL_REMOTE1 (2 << 4) -#define ADT7481_CONV_CHAN_SEL_REMOTE2 (3 << 4) -#define ADT7481_CONV_AVERAGING_L BIT(7) - - -/* Status1 register bits */ -#define ADT7481_STATUS1_LOCAL_THERM_ALARM BIT(0) -#define ADT7481_STATUS1_REMOTE1_THERM_ALARM BIT(1) -#define ADT7481_STATUS1_REMOTE1_OPEN BIT(2) -#define ADT7481_STATUS1_REMOTE1_LOW_ALARM BIT(3) -#define ADT7481_STATUS1_REMOTE1_HIGH_ALARM BIT(4) -#define ADT7481_STATUS1_LOCAL_LOW_ALARM BIT(5) -#define ADT7481_STATUS1_LOCAL_HIGH_ALARM BIT(6) -#define ADT7481_STATUS1_BUSY BIT(7) - -/* Status2 register bits */ -#define ADT7481_STATUS2_ALERT BIT(0) -#define ADT7481_STATUS2_REMOTE2_THERM_ALARM BIT(1) -#define ADT7481_STATUS2_REMOTE2_OPEN BIT(2) -#define ADT7481_STATUS2_REMOTE2_LOW_ALARM BIT(3) -#define ADT7481_STATUS2_REMOTE2_HIGH_ALARM BIT(4) - -/* Consecutive Alert register */ -#define ADT7481_CONSEC_MASK (0xf) -#define ADT7481_CONSEC_1 (0x0) -#define ADT7481_CONSEC_2 (0x2) -#define ADT7481_CONSEC_3 (0x6) -#define ADT7481_CONSEC_4 (0xe) -#define ADT7481_CONSEC_EN_SCL_TIMEOUT BIT(5) -#define ADT7481_CONSEC_EN_SDA_TIMEOUT BIT(6) -#define ADT7481_CONSEC_MASK_LOCAL_ALERT BIT(7) - - -/* Limits */ -#define ADT7481_HYSTERESIS_HIGH_LIMIT 255 -#define ADT7481_HYSTERESIS_LOW_LIMIT 0 - -enum adt7481_power_state { - ADT7481_POWER_OFF = 0, - ADT7481_POWER_ON, - ADT7481_POWER_COUNT -}; - -enum adt7481_channel_id { - ADT7481_CHANNEL_LOCAL, - ADT7481_CHANNEL_REMOTE1, - ADT7481_CHANNEL_REMOTE2, - - ADT7481_CHANNEL_COUNT -}; - -/** - * Get the last polled value of a sensor. - * - * @param idx Index to read. Idx indicates whether to read die - * temperature or external temperature. - * @param temp_ptr Destination for temperature in K. - * - * @return EC_SUCCESS if successful, non-zero if error. - */ -int adt7481_get_val(int idx, int *temp_ptr); - -/** - * Power control function of ADT7481 temperature sensor. - * - * @param power_on ADT7481_POWER_ON: turn ADT7481 sensor on. - * ADT7481_POWER_OFF: shut ADT7481 sensor down. - * - * @return EC_SUCCESS if successful, non-zero if error. - */ -int adt7481_set_power(enum adt7481_power_state power_on); - -/* - * Set ADT7481 ALERT#/THERM2# pin to THERM mode, and give a limit - * for a specific channel. - * - * @param channel specific a channel - * - * @param limit_c High limit temperature, default: 85C - * - * @param hysteresis Hysteresis temperature, default: 10C - * All channels share the same hysteresis - * - * In THERM mode, ALERT# pin will trigger(Low) by itself when any - * channel's temperature is greater( >= )than channel's limit_c, - * and release(High) by itself when channel's temperature is lower - * than (limit_c - hysteresis) - */ -int adt7481_set_therm_limit(int channel, int limit_c, int hysteresis); -#endif /* __CROS_EC_ADT7481_H */ diff --git a/driver/temp_sensor/bd99992gw.c b/driver/temp_sensor/bd99992gw.c deleted file mode 100644 index 0fc8f094b4..0000000000 --- a/driver/temp_sensor/bd99992gw.c +++ /dev/null @@ -1,182 +0,0 @@ -/* 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. - */ - -/* - * BD99992GW PMIC temperature sensor module for Chrome EC. - * Note that ADC / temperature sensor registers are only active while - * the PMIC is in S0. - */ - -#include "bd99992gw.h" -#include "chipset.h" -#include "common.h" -#include "console.h" -#include "gpio.h" -#include "hooks.h" -#include "i2c.h" -#include "temp_sensor.h" -#include "thermistor.h" -#include "timer.h" -#include "util.h" - -/* Console output macros */ -#define CPUTS(outstr) cputs(CC_THERMAL, outstr) -#define CPRINTS(format, args...) cprints(CC_THERMAL, format, ## args) - -/* List of active channels, ordered by pointer register */ -static enum bd99992gw_adc_channel - active_channels[BD99992GW_ADC_POINTER_REG_COUNT]; - -/* - * Use 27ms as the period between ADC conversions, as we will typically be - * sampling temperature sensors every second, and 27ms is the longest - * supported period. - */ -#define ADC_LOOP_PERIOD BD99992GW_ADC1CNTL1_SLP27MS - -static int raw_read8(const int offset, int *data_ptr) -{ - int ret; - ret = i2c_read8(I2C_PORT_THERMAL, BD99992GW_I2C_ADDR_FLAGS, - offset, data_ptr); - if (ret != EC_SUCCESS) - CPRINTS("bd99992gw read fail %d", ret); - return ret; -} - -static int raw_write8(const int offset, int data) -{ - int ret; - ret = i2c_write8(I2C_PORT_THERMAL, BD99992GW_I2C_ADDR_FLAGS, - offset, data); - if (ret != EC_SUCCESS) - CPRINTS("bd99992gw write fail %d", ret); - return ret; -} - -static void bd99992gw_init(void) -{ - int i; - int active_channel_count = 0; - uint8_t pointer_reg = BD99992GW_REG_ADC1ADDR0; - - /* Mark active channels from the board temp sensor table */ - for (i = 0; i < TEMP_SENSOR_COUNT; ++i) - if (temp_sensors[i].read == bd99992gw_get_val) - active_channels[active_channel_count++] = - temp_sensors[i].idx; - - /* Make sure we don't have too many active channels. */ - ASSERT(active_channel_count <= ARRAY_SIZE(active_channels)); - - /* Mark the first unused channel so we know where to stop searching */ - if (active_channel_count != ARRAY_SIZE(active_channels)) - active_channels[active_channel_count] = - BD99992GW_ADC_CHANNEL_NONE; - - /* Now write pointer regs with channel to monitor */ - for (i = 0; i < active_channel_count; ++i) - /* Write stop bit on last channel */ - if (raw_write8(pointer_reg + i, active_channels[i] | - ((i == active_channel_count - 1) ? - BD99992GW_ADC1ADDR_STOP : 0))) - return; - - /* Enable ADC interrupts */ - if (raw_write8(BD99992GW_REG_MADC1INT, 0xf & ~BD99992GW_MADC1INT_RND)) - return; - if (raw_write8(BD99992GW_REG_IRQLVL1MSK, BD99992GW_IRQLVL1MSK_MADC)) - return; - - /* Enable ADC sequencing */ - if (raw_write8(BD99992GW_REG_ADC1CNTL2, BD99992GW_ADC1CNTL2_ADCTHERM)) - return; - - /* Start round-robin conversions at 27ms period */ - raw_write8(BD99992GW_REG_ADC1CNTL1, ADC_LOOP_PERIOD | - BD99992GW_ADC1CNTL1_ADEN | BD99992GW_ADC1CNTL1_ADSTRT); -} -/* - * Some regs only work in S0, so we must initialize on AP startup in - * addition to INIT. - */ -DECLARE_HOOK(HOOK_INIT, bd99992gw_init, HOOK_PRIO_DEFAULT); -DECLARE_HOOK(HOOK_CHIPSET_RESUME, bd99992gw_init, HOOK_PRIO_DEFAULT); - -/* Convert ADC result to temperature in celsius */ -static int bd99992gw_get_temp(uint16_t adc) -{ -#ifdef CONFIG_THERMISTOR_NCP15WB - return ncp15wb_calculate_temp(adc); -#else -#error "Unknown thermistor for bd99992gw" - return 0; -#endif -} - -/* Get temperature from requested sensor */ -int bd99992gw_get_val(int idx, int *temp_ptr) -{ - uint16_t adc; - int i, read, ret; - enum bd99992gw_adc_channel channel; - - /* ADC unit is only functional in S0 */ - if (!chipset_in_state(CHIPSET_STATE_ON)) - return EC_ERROR_NOT_POWERED; - - /* Find requested channel */ - for (i = 0; i < ARRAY_SIZE(active_channels); ++i) { - channel = active_channels[i]; - if (channel == idx || - channel == BD99992GW_ADC_CHANNEL_NONE) - break; - } - - /* Make sure we found it */ - if (i == ARRAY_SIZE(active_channels) || - active_channels[i] != idx) { - CPRINTS("Bad ADC channel %d", idx); - return EC_ERROR_INVAL; - } - - /* Pause conversions */ - ret = raw_write8(0x80, - ADC_LOOP_PERIOD | - BD99992GW_ADC1CNTL1_ADEN | - BD99992GW_ADC1CNTL1_ADSTRT | - BD99992GW_ADC1CNTL1_ADPAUSE); - if (ret) - return ret; - - /* Read 10-bit ADC result */ - ret = raw_read8(BD99992GW_REG_ADC1DATA0L + 2 * i, &read); - if (ret) - return ret; - adc = read; - ret = raw_read8(BD99992GW_REG_ADC1DATA0H + 2 * i, &read); - if (ret) - return ret; - adc |= read << 2; - - /* Convert temperature to C / K */ - *temp_ptr = C_TO_K(bd99992gw_get_temp(adc)); - - /* Clear interrupts */ - ret = raw_write8(BD99992GW_REG_ADC1INT, BD99992GW_ADC1INT_RND); - if (ret) - return ret; - ret = raw_write8(BD99992GW_REG_IRQLVL1, BD99992GW_IRQLVL1_ADC); - if (ret) - return ret; - - /* Resume conversions */ - ret = raw_write8(BD99992GW_REG_ADC1CNTL1, ADC_LOOP_PERIOD | - BD99992GW_ADC1CNTL1_ADEN | BD99992GW_ADC1CNTL1_ADSTRT); - if (ret) - return ret; - - return EC_SUCCESS; -} diff --git a/driver/temp_sensor/bd99992gw.h b/driver/temp_sensor/bd99992gw.h deleted file mode 100644 index c461012c45..0000000000 --- a/driver/temp_sensor/bd99992gw.h +++ /dev/null @@ -1,90 +0,0 @@ -/* 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. - */ - -/* G781 temperature sensor module for Chrome EC */ - -#ifndef __CROS_EC_TEMP_SENSOR_BD99992GW_H -#define __CROS_EC_TEMP_SENSOR_BD99992GW_H - -#define BD99992GW_I2C_ADDR_FLAGS 0x30 - -/* ADC channels */ -enum bd99992gw_adc_channel { - BD99992GW_ADC_CHANNEL_NONE = -1, - BD99992GW_ADC_CHANNEL_BATTERY = 0, - BD99992GW_ADC_CHANNEL_AC = 1, - BD99992GW_ADC_CHANNEL_SYSTHERM0 = 2, - BD99992GW_ADC_CHANNEL_SYSTHERM1 = 3, - BD99992GW_ADC_CHANNEL_SYSTHERM2 = 4, - BD99992GW_ADC_CHANNEL_SYSTHERM3 = 5, - BD99992GW_ADC_CHANNEL_DIE_TEMP = 6, - BD99992GW_ADC_CHANNEL_VDC = 7, - BD99992GW_ADC_CHANNEL_COUNT = 8, -}; - -/* Registers */ -#define BD99992GW_REG_IRQLVL1 0x02 -#define BD99992GW_IRQLVL1_ADC BIT(1) /* ADC IRQ asserted */ - -#define BD99992GW_REG_ADC1INT 0x03 -#define BD99992GW_ADC1INT_RND BIT(0) /* RR cycle completed */ - -#define BD99992GW_REG_MADC1INT 0x0a -#define BD99992GW_MADC1INT_RND BIT(0) /* RR cycle mask */ - -#define BD99992GW_REG_IRQLVL1MSK 0x13 -#define BD99992GW_IRQLVL1MSK_MADC BIT(1) /* ADC IRQ mask */ - -#define BD99992GW_REG_ADC1CNTL1 0x80 -#define BD99992GW_ADC1CNTL1_SLP27MS (0x6 << 3) /* 27ms between pass */ -#define BD99992GW_ADC1CNTL1_NOLOOP (0x7 << 3) /* Single loop pass only */ -#define BD99992GW_ADC1CNTL1_ADPAUSE BIT(2) /* ADC pause */ -#define BD99992GW_ADC1CNTL1_ADSTRT BIT(1) /* ADC start */ -#define BD99992GW_ADC1CNTL1_ADEN BIT(0) /* ADC enable */ - -#define BD99992GW_REG_ADC1CNTL2 0x81 -#define BD99992GW_ADC1CNTL2_ADCTHERM BIT(0) /* Enable ADC sequencing */ - - /* ADC1 Pointer file regs - assign to proper bd99992gw_adc_channel */ -#define BD99992GW_ADC_POINTER_REG_COUNT 8 -#define BD99992GW_REG_ADC1ADDR0 0x82 -#define BD99992GW_REG_ADC1ADDR1 0x83 -#define BD99992GW_REG_ADC1ADDR2 0x84 -#define BD99992GW_REG_ADC1ADDR3 0x85 -#define BD99992GW_REG_ADC1ADDR4 0x86 -#define BD99992GW_REG_ADC1ADDR5 0x87 -#define BD99992GW_REG_ADC1ADDR6 0x88 -#define BD99992GW_REG_ADC1ADDR7 0x89 -#define BD99992GW_ADC1ADDR_STOP BIT(3) /* Last conversion channel */ - -/* Result registers */ -#define BD99992GW_REG_ADC1DATA0L 0x95 -#define BD99992GW_REG_ADC1DATA0H 0x96 -#define BD99992GW_REG_ADC1DATA1L 0x97 -#define BD99992GW_REG_ADC1DATA1H 0x98 -#define BD99992GW_REG_ADC1DATA2L 0x99 -#define BD99992GW_REG_ADC1DATA2H 0x9a -#define BD99992GW_REG_ADC1DATA3L 0x9b -#define BD99992GW_REG_ADC1DATA3H 0x9c -#define BD99992GW_REG_ADC1DATA4L 0x9d -#define BD99992GW_REG_ADC1DATA4H 0x9e -#define BD99992GW_REG_ADC1DATA5L 0x9f -#define BD99992GW_REG_ADC1DATA5H 0xa0 -#define BD99992GW_REG_ADC1DATA6L 0xa1 -#define BD99992GW_REG_ADC1DATA6H 0xa2 -#define BD99992GW_REG_ADC1DATA7L 0xa3 -#define BD99992GW_REG_ADC1DATA7H 0xa4 - -/** - * Get the latest value from the sensor. - * - * @param idx ADC channel to read. - * @param temp_ptr Destination for temperature in K. - * - * @return EC_SUCCESS if successful, non-zero if error. - */ -int bd99992gw_get_val(int idx, int *temp_ptr); - -#endif /* __CROS_EC_TEMP_SENSOR_BD99992GW_H */ diff --git a/driver/temp_sensor/ec_adc.c b/driver/temp_sensor/ec_adc.c deleted file mode 100644 index db174e33dc..0000000000 --- a/driver/temp_sensor/ec_adc.c +++ /dev/null @@ -1,56 +0,0 @@ -/* 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. - */ - -/* EC_ADC driver for Chrome EC */ - -#include "adc.h" -#include "common.h" -#include "console.h" -#include "ec_adc.h" -#include "thermistor.h" -#include "util.h" - -/* Get temperature from requested sensor */ -static int get_temp(int idx, int *temp_ptr) -{ - int temp_raw = 0; - - /* Read 10-bit ADC result */ - temp_raw = adc_read_channel(idx); - - if (temp_raw == ADC_READ_ERROR) - return EC_ERROR_UNKNOWN; - - /* TODO : Need modification here if the result is not 10-bit */ - - /* If there is no thermistor calculation function. - * 1. Add adjusting function like thermistor_ncp15wb.c - * 2. Place function here with ifdef - * 3. define it on board.h - */ -#ifdef CONFIG_THERMISTOR_NCP15WB - *temp_ptr = ncp15wb_calculate_temp((uint16_t) temp_raw); -#else -#error "Unknown thermistor for ec_adc" - return EC_ERROR_UNKNOWN; -#endif - - return EC_SUCCESS; -} - -int ec_adc_get_val(int idx, int *temp_ptr) -{ - int ret; - int temp_c; - - if(idx < 0 || idx >= ADC_CH_COUNT) - return EC_ERROR_INVAL; - - ret = get_temp(idx, &temp_c); - if (ret == EC_SUCCESS) - *temp_ptr = C_TO_K(temp_c); - - return ret; -} diff --git a/driver/temp_sensor/ec_adc.h b/driver/temp_sensor/ec_adc.h deleted file mode 100644 index 8ff213e95d..0000000000 --- a/driver/temp_sensor/ec_adc.h +++ /dev/null @@ -1,24 +0,0 @@ -/* 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. - */ - -/* ec_adc which uses adc and thermistors module for Chrome EC - * Some EC has it's own ADC modules, define here EC's max ADC channels. - * We can consider every channel as a thermal sensor. - */ - -#ifndef __CROS_EC_TEMP_SENSOR_EC_ADC_H -#define __CROS_EC_TEMP_SENSOR_EC_ADC_H - -/** - * Get the latest value from the sensor. - * - * @param idx ADC channel to read. - * @param temp_ptr Destination for temperature in K. - * - * @return EC_SUCCESS if successful, non-zero if error. - */ -int ec_adc_get_val(int idx, int *temp_ptr); - -#endif /* __CROS_EC_TEMP_SENSOR_EC_ADC_H */ diff --git a/driver/temp_sensor/f75303.c b/driver/temp_sensor/f75303.c deleted file mode 100644 index 6b8895a252..0000000000 --- a/driver/temp_sensor/f75303.c +++ /dev/null @@ -1,93 +0,0 @@ -/* Copyright 2018 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. - */ - -/* F75303 temperature sensor module for Chrome EC */ - -#include "common.h" -#include "f75303.h" -#include "i2c.h" -#include "hooks.h" -#include "util.h" -#include "console.h" - -static int temps[F75303_IDX_COUNT]; -static int8_t fake_temp[F75303_IDX_COUNT] = {-1, -1, -1}; - -/** - * Read 8 bits register from temp sensor. - */ -static int raw_read8(const int offset, int *data) -{ - return i2c_read8(I2C_PORT_THERMAL, F75303_I2C_ADDR_FLAGS, - offset, data); -} - -static int get_temp(const int offset, int *temp) -{ - int rv; - int temp_raw = 0; - - rv = raw_read8(offset, &temp_raw); - if (rv != 0) - return rv; - - *temp = C_TO_K(temp_raw); - return EC_SUCCESS; -} - -int f75303_get_val(int idx, int *temp) -{ - if (idx < 0 || F75303_IDX_COUNT <= idx) - return EC_ERROR_INVAL; - - if (fake_temp[idx] != -1) { - *temp = C_TO_K(fake_temp[idx]); - return EC_SUCCESS; - } - - *temp = temps[idx]; - return EC_SUCCESS; -} - -static void f75303_sensor_poll(void) -{ - get_temp(F75303_TEMP_LOCAL, &temps[F75303_IDX_LOCAL]); - get_temp(F75303_TEMP_REMOTE1, &temps[F75303_IDX_REMOTE1]); - get_temp(F75303_TEMP_REMOTE2, &temps[F75303_IDX_REMOTE2]); -} -DECLARE_HOOK(HOOK_SECOND, f75303_sensor_poll, HOOK_PRIO_TEMP_SENSOR); - -static int f75303_set_fake_temp(int argc, char **argv) -{ - int index; - int value; - char *e; - - if (argc != 3) - return EC_ERROR_PARAM_COUNT; - - index = strtoi(argv[1], &e, 0); - if ((*e) || (index < 0) || (index >= F75303_IDX_COUNT)) - return EC_ERROR_PARAM1; - - if (!strcasecmp(argv[2], "off")) { - fake_temp[index] = -1; - ccprintf("Turn off fake temp mode for sensor %u.\n", index); - return EC_SUCCESS; - } - - value = strtoi(argv[2], &e, 0); - - if ((*e) || (value < 0) || (value > 100)) - return EC_ERROR_PARAM2; - - fake_temp[index] = value; - ccprintf("Force sensor %u = %uC.\n", index, value); - - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(f75303, f75303_set_fake_temp, - "<index> <value>|off", - "Set fake temperature of sensor f75303."); diff --git a/driver/temp_sensor/f75303.h b/driver/temp_sensor/f75303.h deleted file mode 100644 index a4bdcbf872..0000000000 --- a/driver/temp_sensor/f75303.h +++ /dev/null @@ -1,36 +0,0 @@ -/* Copyright 2018 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. - */ - -/* F75303 temperature sensor module for Chrome EC */ - -#ifndef __CROS_EC_F75303_H -#define __CROS_EC_F75303_H - -#define F75303_I2C_ADDR_FLAGS 0x4C - -enum f75303_index { - F75303_IDX_LOCAL = 0, - F75303_IDX_REMOTE1, - F75303_IDX_REMOTE2, - F75303_IDX_COUNT, -}; - -/* F75303 register */ -#define F75303_TEMP_LOCAL 0x00 -#define F75303_TEMP_REMOTE1 0x01 -#define F75303_TEMP_REMOTE2 0x23 - -/** - * Get the last polled value of a sensor. - * - * @param idx Index to read. Idx indicates whether to read die - * temperature or external temperature. - * @param temp Destination for temperature in K. - * - * @return EC_SUCCESS if successful, non-zero if error. - */ -int f75303_get_val(int idx, int *temp); - -#endif /* __CROS_EC_F75303_H */ diff --git a/driver/temp_sensor/g753.c b/driver/temp_sensor/g753.c deleted file mode 100644 index 857263c161..0000000000 --- a/driver/temp_sensor/g753.c +++ /dev/null @@ -1,192 +0,0 @@ -/* Copyright 2019 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. - */ - -/* G753 temperature sensor module for Chrome EC */ - -#include "common.h" -#include "console.h" -#include "g753.h" -#include "gpio.h" -#include "i2c.h" -#include "hooks.h" -#include "util.h" - -static int temp_val_local; - -/** - * Determine whether the sensor is powered. - * - * @return non-zero the g753 sensor is powered. - */ -static int has_power(void) -{ -#ifdef CONFIG_TEMP_SENSOR_POWER_GPIO - return gpio_get_level(CONFIG_TEMP_SENSOR_POWER_GPIO); -#else - return 1; -#endif -} - -static int raw_read8(const int offset, int *data_ptr) -{ - return i2c_read8(I2C_PORT_THERMAL, G753_I2C_ADDR_FLAGS, - offset, data_ptr); -} - -#ifdef CONFIG_CMD_TEMP_SENSOR -static int raw_write8(const int offset, int data) -{ - return i2c_write8(I2C_PORT_THERMAL, G753_I2C_ADDR_FLAGS, - offset, data); -} -#endif - -static int get_temp(const int offset, int *temp_ptr) -{ - int rv; - int temp_raw = 0; - - rv = raw_read8(offset, &temp_raw); - if (rv < 0) - return rv; - - *temp_ptr = (int)(int8_t)temp_raw; - return EC_SUCCESS; -} - -#ifdef CONFIG_CMD_TEMP_SENSOR -static int set_temp(const int offset, int temp) -{ - if (temp < -127 || temp > 127) - return EC_ERROR_INVAL; - - return raw_write8(offset, (uint8_t)temp); -} -#endif - -int g753_get_val(int idx, int *temp_ptr) -{ - if (!has_power()) - return EC_ERROR_NOT_POWERED; - - switch (idx) { - case G753_IDX_INTERNAL: - *temp_ptr = temp_val_local; - break; - default: - return EC_ERROR_UNKNOWN; - } - - return EC_SUCCESS; -} - -static void temp_sensor_poll(void) -{ - if (!has_power()) - return; - - get_temp(G753_TEMP_LOCAL, &temp_val_local); - temp_val_local = C_TO_K(temp_val_local); -} -DECLARE_HOOK(HOOK_SECOND, temp_sensor_poll, HOOK_PRIO_TEMP_SENSOR); - -#ifdef CONFIG_CMD_TEMP_SENSOR -static void print_temps(const char *name, - const int temp_reg, - const int high_limit_reg) -{ - int value; - - ccprintf("%s:\n", name); - - if (get_temp(temp_reg, &value) == EC_SUCCESS) - ccprintf(" Temp: %3dC\n", value); - - if (get_temp(high_limit_reg, &value) == EC_SUCCESS) - ccprintf(" High Alarm: %3dC\n", value); - -} - -static int print_status(void) -{ - int value; - - if (!has_power()) { - ccprintf("ERROR: Temp sensor not powered.\n"); - return EC_ERROR_NOT_POWERED; - } - - print_temps("Local", G753_TEMP_LOCAL, - G753_LOCAL_TEMP_HIGH_LIMIT_R); - - ccprintf("\n"); - - if (raw_read8(G753_STATUS, &value) == EC_SUCCESS) - ccprintf("STATUS: %pb\n", BINARY_VALUE(value, 8)); - - if (raw_read8(G753_CONFIGURATION_R, &value) == EC_SUCCESS) - ccprintf("CONFIG: %pb\n", BINARY_VALUE(value, 8)); - - return EC_SUCCESS; -} - -static int command_g753(int argc, char **argv) -{ - char *command; - char *e; - int data; - int offset; - int rv; - - if (!has_power()) { - ccprintf("ERROR: Temp sensor not powered.\n"); - return EC_ERROR_NOT_POWERED; - } - - /* If no args just print status */ - if (argc == 1) - return print_status(); - - if (argc < 3) - return EC_ERROR_PARAM_COUNT; - - command = argv[1]; - offset = strtoi(argv[2], &e, 0); - if (*e || offset < 0 || offset > 255) - return EC_ERROR_PARAM2; - - if (!strcasecmp(command, "getbyte")) { - rv = raw_read8(offset, &data); - if (rv < 0) - return rv; - ccprintf("Byte at offset 0x%02x is %pb\n", - offset, BINARY_VALUE(data, 8)); - return rv; - } - - /* Remaining commands are of the form "g753 set-command offset data" */ - if (argc != 4) - return EC_ERROR_PARAM_COUNT; - - data = strtoi(argv[3], &e, 0); - if (*e) - return EC_ERROR_PARAM3; - - if (!strcasecmp(command, "settemp")) { - ccprintf("Setting 0x%02x to %dC\n", offset, data); - rv = set_temp(offset, data); - } else if (!strcasecmp(command, "setbyte")) { - ccprintf("Setting 0x%02x to 0x%02x\n", offset, data); - rv = raw_write8(offset, data); - } else - return EC_ERROR_PARAM1; - - return rv; -} -DECLARE_CONSOLE_COMMAND(g753, command_g753, - "[settemp|setbyte <offset> <value>] or [getbyte <offset>]. " - "Temps in Celsius.", - "Print g753 temp sensor status or set parameters."); -#endif diff --git a/driver/temp_sensor/g753.h b/driver/temp_sensor/g753.h deleted file mode 100644 index 04c412bfbb..0000000000 --- a/driver/temp_sensor/g753.h +++ /dev/null @@ -1,53 +0,0 @@ -/* Copyright 2019 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. - */ - -/* G753 temperature sensor module for Chrome EC */ - -#ifndef __CROS_EC_G753_H -#define __CROS_EC_G753_H - - -#define G753_I2C_ADDR_FLAGS 0x48 - -#define G753_IDX_INTERNAL 0 - -/* G753 register */ -#define G753_TEMP_LOCAL 0x00 -#define G753_STATUS 0x02 -#define G753_CONFIGURATION_R 0x03 -#define G753_CONVERSION_RATE_R 0x04 -#define G753_LOCAL_TEMP_HIGH_LIMIT_R 0x05 -#define G753_CONFIGURATION_W 0x09 -#define G753_CONVERSION_RATE_W 0x0A -#define G753_LOCAL_TEMP_HIGH_LIMIT_W 0x0B -#define G753_ONESHOT 0x0F -#define G753_Customer_Data_Log_Register_1 0x2D -#define G753_Customer_Data_Log_Register_2 0x2E -#define G753_Customer_Data_Log_Register_3 0x2F -#define G753_ALERT_MODE 0xBF -#define G753_CHIP_ID 0xFD -#define G753_VENDOR_ID 0xFE -#define G753_DEVICE_ID 0xFF - -/* Config register bits */ -#define G753_CONFIGURATION_STANDBY BIT(6) -#define G753_CONFIGURATION_ALERT_MASK BIT(7) - -/* Status register bits */ -#define G753_STATUS_LOCAL_TEMP_HIGH_ALARM BIT(6) -#define G753_STATUS_BUSY BIT(7) - -/** - * Get the last polled value of a sensor. - * - * @param idx Index to read. Idx indicates whether to read die - * temperature or external temperature. - * @param temp_ptr Destination for temperature in K. - * - * @return EC_SUCCESS if successful, non-zero if error. - */ -int g753_get_val(int idx, int *temp_ptr); - -#endif /* __CROS_EC_G753_H */ diff --git a/driver/temp_sensor/g78x.c b/driver/temp_sensor/g78x.c deleted file mode 100644 index aef13d3d68..0000000000 --- a/driver/temp_sensor/g78x.c +++ /dev/null @@ -1,238 +0,0 @@ -/* 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. - */ - -/* G781/G782 temperature sensor module for Chrome EC */ - -#include "common.h" -#include "console.h" -#include "g78x.h" -#include "gpio.h" -#include "i2c.h" -#include "hooks.h" -#include "util.h" - -static int temp_val_local; -static int temp_val_remote1; -#ifdef CONFIG_TEMP_SENSOR_G782 -static int temp_val_remote2; -#endif - -/** - * Determine whether the sensor is powered. - * - * @return non-zero the g781/g782 sensor is powered. - */ -static int has_power(void) -{ -#ifdef CONFIG_TEMP_SENSOR_POWER_GPIO - return gpio_get_level(CONFIG_TEMP_SENSOR_POWER_GPIO); -#else - return 1; -#endif -} - -static int raw_read8(const int offset, int *data_ptr) -{ - return i2c_read8(I2C_PORT_THERMAL, G78X_I2C_ADDR_FLAGS, - offset, data_ptr); -} - -#ifdef CONFIG_CMD_TEMP_SENSOR -static int raw_write8(const int offset, int data) -{ - return i2c_write8(I2C_PORT_THERMAL, G78X_I2C_ADDR_FLAGS, - offset, data); -} -#endif - -static int get_temp(const int offset, int *temp_ptr) -{ - int rv; - int temp_raw = 0; - - rv = raw_read8(offset, &temp_raw); - if (rv < 0) - return rv; - - *temp_ptr = (int)(int8_t)temp_raw; - return EC_SUCCESS; -} - -#ifdef CONFIG_CMD_TEMP_SENSOR -static int set_temp(const int offset, int temp) -{ - if (temp < -127 || temp > 127) - return EC_ERROR_INVAL; - - return raw_write8(offset, (uint8_t)temp); -} -#endif - -int g78x_get_val(int idx, int *temp_ptr) -{ - if (!has_power()) - return EC_ERROR_NOT_POWERED; - - switch (idx) { - case G78X_IDX_INTERNAL: - *temp_ptr = temp_val_local; - break; - case G78X_IDX_EXTERNAL1: - *temp_ptr = temp_val_remote1; - break; -#ifdef CONFIG_TEMP_SENSOR_G782 - case G78X_IDX_EXTERNAL2: - *temp_ptr = temp_val_remote2; - break; -#endif - default: - return EC_ERROR_UNKNOWN; - } - - return EC_SUCCESS; -} - -static void temp_sensor_poll(void) -{ - if (!has_power()) - return; - - get_temp(G78X_TEMP_LOCAL, &temp_val_local); - temp_val_local = C_TO_K(temp_val_local); - - get_temp(G78X_TEMP_REMOTE1, &temp_val_remote1); - temp_val_remote1 = C_TO_K(temp_val_remote1); - -#ifdef CONFIG_TEMP_SENSOR_G782 - get_temp(G78X_TEMP_REMOTE2, &temp_val_remote2); - temp_val_remote2 = C_TO_K(temp_val_remote2); -#endif -} -DECLARE_HOOK(HOOK_SECOND, temp_sensor_poll, HOOK_PRIO_TEMP_SENSOR); - -#ifdef CONFIG_CMD_TEMP_SENSOR -static void print_temps(const char *name, - const int temp_reg, - const int therm_limit_reg, - const int high_limit_reg, - const int low_limit_reg) -{ - int value; - - ccprintf("%s:\n", name); - - if (get_temp(temp_reg, &value) == EC_SUCCESS) - ccprintf(" Temp: %3dC\n", value); - - if (get_temp(therm_limit_reg, &value) == EC_SUCCESS) - ccprintf(" Therm Trip: %3dC\n", value); - - if (get_temp(high_limit_reg, &value) == EC_SUCCESS) - ccprintf(" High Alarm: %3dC\n", value); - - if (get_temp(low_limit_reg, &value) == EC_SUCCESS) - ccprintf(" Low Alarm: %3dC\n", value); -} - -static int print_status(void) -{ - int value; - - if (!has_power()) { - ccprintf("ERROR: Temp sensor not powered.\n"); - return EC_ERROR_NOT_POWERED; - } - - print_temps("Local", G78X_TEMP_LOCAL, - G78X_LOCAL_TEMP_THERM_LIMIT, - G78X_LOCAL_TEMP_HIGH_LIMIT_R, - G78X_LOCAL_TEMP_LOW_LIMIT_R); - - print_temps("Remote1", G78X_TEMP_REMOTE1, - G78X_REMOTE1_TEMP_THERM_LIMIT, - G78X_REMOTE1_TEMP_HIGH_LIMIT_R, - G78X_REMOTE1_TEMP_LOW_LIMIT_R); - -#ifdef CONFIG_TEMP_SENSOR_G782 - print_temps("Remote2", G78X_TEMP_REMOTE1, - G78X_REMOTE2_TEMP_THERM_LIMIT, - G78X_REMOTE2_TEMP_HIGH_LIMIT_R, - G78X_REMOTE2_TEMP_LOW_LIMIT_R); -#endif - - ccprintf("\n"); - - if (raw_read8(G78X_STATUS, &value) == EC_SUCCESS) - ccprintf("STATUS: %pb\n", BINARY_VALUE(value, 8)); - -#ifdef CONFIG_TEMP_SENSOR_G782 - if (raw_read8(G78X_STATUS1, &value) == EC_SUCCESS) - ccprintf("STATUS1: %pb\n", BINARY_VALUE(value, 8)); -#endif - - if (raw_read8(G78X_CONFIGURATION_R, &value) == EC_SUCCESS) - ccprintf("CONFIG: %pb\n", BINARY_VALUE(value, 8)); - - return EC_SUCCESS; -} - -static int command_g78x(int argc, char **argv) -{ - char *command; - char *e; - int data; - int offset; - int rv; - - if (!has_power()) { - ccprintf("ERROR: Temp sensor not powered.\n"); - return EC_ERROR_NOT_POWERED; - } - - /* If no args just print status */ - if (argc == 1) - return print_status(); - - if (argc < 3) - return EC_ERROR_PARAM_COUNT; - - command = argv[1]; - offset = strtoi(argv[2], &e, 0); - if (*e || offset < 0 || offset > 255) - return EC_ERROR_PARAM2; - - if (!strcasecmp(command, "getbyte")) { - rv = raw_read8(offset, &data); - if (rv < 0) - return rv; - ccprintf("Byte at offset 0x%02x is %pb\n", - offset, BINARY_VALUE(data, 8)); - return rv; - } - - /* Remaining commands are of the form "g78x set-command offset data" */ - if (argc != 4) - return EC_ERROR_PARAM_COUNT; - - data = strtoi(argv[3], &e, 0); - if (*e) - return EC_ERROR_PARAM3; - - if (!strcasecmp(command, "settemp")) { - ccprintf("Setting 0x%02x to %dC\n", offset, data); - rv = set_temp(offset, data); - } else if (!strcasecmp(command, "setbyte")) { - ccprintf("Setting 0x%02x to 0x%02x\n", offset, data); - rv = raw_write8(offset, data); - } else - return EC_ERROR_PARAM1; - - return rv; -} -DECLARE_CONSOLE_COMMAND(g78x, command_g78x, - "[settemp|setbyte <offset> <value>] or [getbyte <offset>]. " - "Temps in Celsius.", - "Print g781/g782 temp sensor status or set parameters."); -#endif diff --git a/driver/temp_sensor/g78x.h b/driver/temp_sensor/g78x.h deleted file mode 100644 index fdd987fcbd..0000000000 --- a/driver/temp_sensor/g78x.h +++ /dev/null @@ -1,140 +0,0 @@ -/* 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. - */ - -/* G781/G782 temperature sensor module for Chrome EC */ - -#ifndef __CROS_EC_G78X_H -#define __CROS_EC_G78X_H - -#if defined(CONFIG_TEMP_SENSOR_G781) && defined(CONFIG_TEMP_SENSOR_G782) -#error Cannot support both G781 and G782 together! -#endif - -#define G78X_I2C_ADDR_FLAGS 0x4C - -#define G78X_IDX_INTERNAL 0 -#define G78X_IDX_EXTERNAL1 1 -#define G78X_IDX_EXTERNAL2 2 - -#if defined(CONFIG_TEMP_SENSOR_G781) -/* G781 register */ -#define G78X_TEMP_LOCAL 0x00 -#define G78X_TEMP_REMOTE1 0x01 -#define G78X_STATUS 0x02 -#define G78X_CONFIGURATION_R 0x03 -#define G78X_CONVERSION_RATE_R 0x04 -#define G78X_LOCAL_TEMP_HIGH_LIMIT_R 0x05 -#define G78X_LOCAL_TEMP_LOW_LIMIT_R 0x06 -#define G78X_REMOTE1_TEMP_HIGH_LIMIT_R 0x07 -#define G78X_REMOTE1_TEMP_LOW_LIMIT_R 0x08 -#define G78X_CONFIGURATION_W 0x09 -#define G78X_CONVERSION_RATE_W 0x0a -#define G78X_LOCAL_TEMP_HIGH_LIMIT_W 0x0b -#define G78X_LOCAL_TEMP_LOW_LIMIT_W 0x0c -#define G78X_REMOTE1_TEMP_HIGH_LIMIT_W 0x0d -#define G78X_REMOTE1_TEMP_LOW_LIMIT_W 0x0e -#define G78X_ONESHOT 0x0f -#define G78X_REMOTE1_TEMP_EXTENDED 0x10 -#define G78X_REMOTE1_TEMP_OFFSET_HIGH 0x11 -#define G78X_REMOTE1_TEMP_OFFSET_EXTD 0x12 -#define G78X_REMOTE1_T_HIGH_LIMIT_EXTD 0x13 -#define G78X_REMOTE1_T_LOW_LIMIT_EXTD 0x14 -#define G78X_REMOTE1_TEMP_THERM_LIMIT 0x19 -#define G78X_LOCAL_TEMP_THERM_LIMIT 0x20 -#define G78X_THERM_HYSTERESIS 0x21 -#define G78X_ALERT_FAULT_QUEUE_CODE 0x22 -#define G78X_MANUFACTURER_ID 0xFE -#define G78X_DEVICE_ID 0xFF - -/* Config register bits */ -#define G78X_CONFIGURATION_STANDBY BIT(6) -#define G78X_CONFIGURATION_ALERT_MASK BIT(7) - -/* Status register bits */ -#define G78X_STATUS_LOCAL_TEMP_THERM_ALARM BIT(0) -#define G78X_STATUS_REMOTE1_TEMP_THERM_ALARM BIT(1) -#define G78X_STATUS_REMOTE1_TEMP_FAULT BIT(2) -#define G78X_STATUS_REMOTE1_TEMP_LOW_ALARM BIT(3) -#define G78X_STATUS_REMOTE1_TEMP_HIGH_ALARM BIT(4) -#define G78X_STATUS_LOCAL_TEMP_LOW_ALARM BIT(5) -#define G78X_STATUS_LOCAL_TEMP_HIGH_ALARM BIT(6) -#define G78X_STATUS_BUSY BIT(7) - -#elif defined(CONFIG_TEMP_SENSOR_G782) -/* G782 register */ -#define G78X_TEMP_LOCAL 0x00 -#define G78X_TEMP_REMOTE1 0x01 -#define G78X_TEMP_REMOTE2 0x02 -#define G78X_STATUS 0x03 -#define G78X_CONFIGURATION_R 0x04 -#define G78X_CONFIGURATION_W 0x04 -#define G78X_CONVERSION_RATE_R 0x05 -#define G78X_CONVERSION_RATE_W 0x05 -#define G78X_LOCAL_TEMP_HIGH_LIMIT_R 0x06 -#define G78X_LOCAL_TEMP_HIGH_LIMIT_W 0x06 -#define G78X_LOCAL_TEMP_LOW_LIMIT_R 0x07 -#define G78X_LOCAL_TEMP_LOW_LIMIT_W 0x07 -#define G78X_REMOTE1_TEMP_HIGH_LIMIT_R 0x08 -#define G78X_REMOTE1_TEMP_HIGH_LIMIT_W 0x08 -#define G78X_REMOTE1_TEMP_LOW_LIMIT_R 0x09 -#define G78X_REMOTE1_TEMP_LOW_LIMIT_W 0x09 -#define G78X_REMOTE2_TEMP_HIGH_LIMIT_R 0x0a -#define G78X_REMOTE2_TEMP_HIGH_LIMIT_W 0x0a -#define G78X_REMOTE2_TEMP_LOW_LIMIT_R 0x0b -#define G78X_REMOTE2_TEMP_LOW_LIMIT_W 0x0b -#define G78X_ONESHOT 0x0c -#define G78X_REMOTE1_TEMP_EXTENDED 0x0d -#define G78X_REMOTE1_TEMP_OFFSET_HIGH 0x0e -#define G78X_REMOTE1_TEMP_OFFSET_EXTD 0x0f -#define G78X_REMOTE1_T_HIGH_LIMIT_EXTD 0x10 -#define G78X_REMOTE1_T_LOW_LIMIT_EXTD 0x11 -#define G78X_REMOTE1_TEMP_THERM_LIMIT 0x12 -#define G78X_REMOTE2_TEMP_EXTENDED 0x13 -#define G78X_REMOTE2_TEMP_OFFSET_HIGH 0x14 -#define G78X_REMOTE2_TEMP_OFFSET_EXTD 0x15 -#define G78X_REMOTE2_T_HIGH_LIMIT_EXTD 0x16 -#define G78X_REMOTE2_T_LOW_LIMIT_EXTD 0x17 -#define G78X_REMOTE2_TEMP_THERM_LIMIT 0x18 -#define G78X_STATUS1 0x19 -#define G78X_LOCAL_TEMP_THERM_LIMIT 0x20 -#define G78X_THERM_HYSTERESIS 0x21 -#define G78X_ALERT_FAULT_QUEUE_CODE 0x22 -#define G78X_MANUFACTURER_ID 0xFE -#define G78X_DEVICE_ID 0xFF - -/* Config register bits */ -#define G78X_CONFIGURATION_REMOTE2_DIS BIT(5) -#define G78X_CONFIGURATION_STANDBY BIT(6) -#define G78X_CONFIGURATION_ALERT_MASK BIT(7) - -/* Status register bits */ -#define G78X_STATUS_LOCAL_TEMP_LOW_ALARM BIT(0) -#define G78X_STATUS_LOCAL_TEMP_HIGH_ALARM BIT(1) -#define G78X_STATUS_LOCAL_TEMP_THERM_ALARM BIT(2) -#define G78X_STATUS_REMOTE2_TEMP_THERM_ALARM BIT(3) -#define G78X_STATUS_REMOTE1_TEMP_THERM_ALARM BIT(4) -#define G78X_STATUS_REMOTE2_TEMP_FAULT BIT(5) -#define G78X_STATUS_REMOTE1_TEMP_FAULT BIT(6) -#define G78X_STATUS_BUSY BIT(7) - -/* Status1 register bits */ -#define G78X_STATUS_REMOTE2_TEMP_LOW_ALARM BIT(4) -#define G78X_STATUS_REMOTE2_TEMP_HIGH_ALARM BIT(5) -#define G78X_STATUS_REMOTE1_TEMP_LOW_ALARM BIT(6) -#define G78X_STATUS_REMOTE1_TEMP_HIGH_ALARM BIT(7) -#endif - -/** - * Get the last polled value of a sensor. - * - * @param idx Index to read. Idx indicates whether to read die - * temperature or external temperature. - * @param temp_ptr Destination for temperature in K. - * - * @return EC_SUCCESS if successful, non-zero if error. - */ -int g78x_get_val(int idx, int *temp_ptr); - -#endif /* __CROS_EC_G78X_H */ diff --git a/driver/temp_sensor/sb_tsi.c b/driver/temp_sensor/sb_tsi.c deleted file mode 100644 index a806ff395f..0000000000 --- a/driver/temp_sensor/sb_tsi.c +++ /dev/null @@ -1,41 +0,0 @@ -/* 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. - */ - -/* - * SB-TSI: SB Temperature Sensor Interface. - * This is an I2C slave temp sensor on the AMD Stony Ridge FT4 SOC. - */ - -#include "chipset.h" -#include "common.h" -#include "console.h" -#include "gpio.h" -#include "hooks.h" -#include "i2c.h" -#include "sb_tsi.h" -#include "util.h" - -static int raw_read8(const int offset, int *data_ptr) -{ - return i2c_read8(I2C_PORT_THERMAL, SB_TSI_I2C_ADDR_FLAGS, - offset, data_ptr); -} - -int sb_tsi_get_val(int idx, int *temp_ptr) -{ - int ret; - /* There is only one temp sensor on the FT4 */ - if (idx != 0) - return EC_ERROR_PARAM1; - /* FT4 SB-TSI sensor only powered in S0 */ - if (!chipset_in_state(CHIPSET_STATE_ON)) - return EC_ERROR_NOT_POWERED; - /* Read the value over I2C */ - ret = raw_read8(SB_TSI_TEMP_H, temp_ptr); - if (ret) - return ret; - *temp_ptr = C_TO_K(*temp_ptr); - return EC_SUCCESS; -} diff --git a/driver/temp_sensor/sb_tsi.h b/driver/temp_sensor/sb_tsi.h deleted file mode 100644 index ae61e4e34d..0000000000 --- a/driver/temp_sensor/sb_tsi.h +++ /dev/null @@ -1,46 +0,0 @@ -/* 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. - */ - -/* - * SB-TSI: SB Temperature Sensor Interface. - * This is an I2C slave temp sensor on the AMD Stony Ridge FT4 SOC. - */ - -#ifndef __CROS_EC_SB_TSI_H -#define __CROS_EC_SB_TSI_H - -#define SB_TSI_I2C_ADDR_FLAGS 0x4C - -/* G781 register */ -#define SB_TSI_TEMP_H 0x01 -#define SB_TSI_STATUS 0x02 -#define SB_TSI_CONFIG_1 0x03 -#define SB_TSI_UPDATE_RATE 0x04 -#define SB_TSI_HIGH_TEMP_THRESHOLD_H 0x07 -#define SB_TSI_LOW_TEMP_THRESHOLD_H 0x08 -#define SB_TSI_CONFIG_2 0x09 -#define SB_TSI_TEMP_L 0x10 -#define SB_TSI_TEMP_OFFSET_H 0x11 -#define SB_TSI_TEMP_OFFSET_L 0x12 -#define SB_TSI_HIGH_TEMP_THRESHOLD_L 0x13 -#define SB_TSI_LOW_TEMP_THRESHOLD_L 0x14 -#define SB_TSI_TIMEOUT_CONFIG 0x22 -#define SB_TSI_PSTATE_LIMIT_CONFIG 0x2F -#define SB_TSI_ALERT_THRESHOLD 0x32 -#define SB_TSI_ALERT_CONFIG 0xBF -#define SB_TSI_MANUFACTURE_ID 0xFE -#define SB_TSI_REVISION 0xFF - -/** - * Get the value of a sensor in K. - * - * @param idx Index to read. Only 0 is valid for sb_tsi. - * @param temp_ptr Destination for temperature in K. - * - * @return EC_SUCCESS if successful, non-zero if error. - */ -int sb_tsi_get_val(int idx, int *temp_ptr); - -#endif /* __CROS_EC_SB_TSI_H */ diff --git a/driver/temp_sensor/tmp006.c b/driver/temp_sensor/tmp006.c deleted file mode 100644 index e4794ccc4a..0000000000 --- a/driver/temp_sensor/tmp006.c +++ /dev/null @@ -1,504 +0,0 @@ -/* Copyright 2014 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. - */ - -/* TMP006 temperature sensor module for Chrome EC */ - -#include "common.h" -#include "console.h" -#include "gpio.h" -#include "hooks.h" -#include "host_command.h" -#include "i2c.h" -#include "math.h" -#include "task.h" -#include "temp_sensor.h" -#include "tmp006.h" -#include "util.h" - -/* Console output macros */ -#define CPUTS(outstr) cputs(CC_THERMAL, outstr) -#define CPRINTS(format, args...) cprints(CC_THERMAL, format, ## args) - -/* - * Alg 0 was what's in the TMP006 User's Guide. Alg 1 is Alg 0, but with - * some filters applied to the Tdie input and Tobj output (see - * crosbug.com/p/32260). - */ -#define ALGORITHM_NUM 1 -#define ALGORITHM_PARAMS 12 - -/* Flags for tdata->fail */ -#define FAIL_INIT BIT(0) /* Just initialized */ -#define FAIL_POWER BIT(1) /* Sensor not powered */ -#define FAIL_I2C BIT(2) /* I2C communication error */ -#define FAIL_NOT_READY BIT(3) /* Data not ready */ - -/* State and conversion factors to track for each sensor */ -struct tmp006_data_t { - /* chip info */ - int16_t v_raw; /* TMP006_REG_VOBJ */ - int16_t t_raw0; /* TMP006_REG_TDIE */ - int fail; /* Fail flags; non-zero if last read failed */ - /* calibration params */ - float s0, a1, a2; /* Sensitivity factors */ - float b0, b1, b2; /* Self-heating correction */ - float c2; /* Seebeck effect */ - float d0, d1, ds; /* Tdie filter and slope adjustment */ - float e0, e1; /* Tobj output filter */ - /* FIR filter stages */ - float tdie1, tobj1; -}; -static struct tmp006_data_t tmp006_data[TMP006_COUNT]; - -/* Default state and conversion factors */ -static const struct tmp006_data_t tmp006_data_default = { - .fail = FAIL_INIT, - - /* Alg 0 params from User's Guide */ - .s0 = 0.0f, /* zero == "uncalibrated" */ - .a1 = 1.75e-3f, - .a2 = -1.678e-5f, - .b0 = -2.94e-5f, - .b1 = -5.7e-7f, - .b2 = 4.63e-9f, - .c2 = 13.4f, - - /* Additional Alg 1 filter params */ - .d0 = 0.2f, - .d1 = 0.8f, - .ds = 1.48e-4, - .e0 = 0.1f, - .e1 = 0.9f, -}; - -static int tmp006_has_power(int idx) -{ -#ifdef CONFIG_TEMP_SENSOR_POWER_GPIO - return gpio_get_level(CONFIG_TEMP_SENSOR_POWER_GPIO); -#else - return 1; -#endif -} - -static void tmp006_poll_sensor(int sensor_id) -{ - struct tmp006_data_t *tdata = tmp006_data + sensor_id; - int t, v, rv; - int addr_flags = tmp006_sensors[sensor_id].addr_flags; - - /* Invalidate the filter history if there is any error */ - if (tdata->fail) { - tdata->tdie1 = 0.0f; - tdata->tobj1 = 0.0; - } - - if (!tmp006_has_power(sensor_id)) { - tdata->fail |= FAIL_POWER; - return; - } - - /* - * If sensor has just initialized and/or has lost power, wait for - * data ready; otherwise, we read garbage data. - */ - if (tdata->fail & (FAIL_POWER | FAIL_INIT)) { - rv = i2c_read16(TMP006_PORT(addr_flags), - TMP006_REG(addr_flags), - TMP006_REG_CONFIG, &v); - if (rv) { - tdata->fail |= FAIL_I2C; - return; - } else if (!(v & 0x80)) { - /* Bit 7 is the Data Ready bit */ - tdata->fail |= FAIL_NOT_READY; - return; - } - } - - rv = i2c_read16(TMP006_PORT(addr_flags), - TMP006_REG(addr_flags), - TMP006_REG_TDIE, &t); - if (rv) { - tdata->fail |= FAIL_I2C; - return; - } - - rv = i2c_read16(TMP006_PORT(addr_flags), - TMP006_REG(addr_flags), - TMP006_REG_VOBJ, &v); - if (rv) { - tdata->fail |= FAIL_I2C; - return; - } - - tdata->t_raw0 = t; - tdata->v_raw = v; - - tdata->fail = 0; -} - -/*****************************************************************************/ -/* Hooks */ - -static void tmp006_init(void) -{ - int i; - - for (i = 0; i < TMP006_COUNT; ++i) - tmp006_data[i] = tmp006_data_default; -} -DECLARE_HOOK(HOOK_INIT, tmp006_init, HOOK_PRIO_DEFAULT); - -static void tmp006_poll(void) -{ - int i; - - for (i = 0; i < TMP006_COUNT; ++i) - tmp006_poll_sensor(i); -} -DECLARE_HOOK(HOOK_SECOND, tmp006_poll, HOOK_PRIO_TEMP_SENSOR); - -/*****************************************************************************/ -/* Interface to the rest of the EC */ - -/* This just returns Tdie */ -static int tmp006_read_die_temp_k(const struct tmp006_data_t *tdata, - int *temp_ptr) -{ - if (tdata->fail) - return EC_ERROR_UNKNOWN; - - /* Tdie reg is signed 1/128 degrees C, resolution 1/32 degrees */ - *temp_ptr = (int)tdata->t_raw0 / 128 + 273; - return EC_SUCCESS; -} - -/* - * This uses Tdie and Vobj and a bunch of magic parameters to calculate the - * object temperature, Tobj. - */ -static int tmp006_read_object_temp_k(struct tmp006_data_t *tdata, - int *temp_ptr) -{ - float tdie, vobj; - float tx, s, vos, vx, fv, tobj, t4; - float tdie_filtered, tdie_slope, tobj_filtered; - - if (tdata->fail) - return EC_ERROR_UNKNOWN; - - if (!tdata->s0) - return EC_ERROR_NOT_CALIBRATED; - - /* Tdie reg is signed 1/128 degrees C, resolution 1/32 degrees - * We need degrees K */ - tdie = (float)tdata->t_raw0 / 128.0f + 273.15f; - /* Vobj reg is signed int, LSB = 156.25 nV - * We need volts */ - vobj = (float)tdata->v_raw / 156.25f * 1e-9f; - - /* Alg1: apply filter to tdie. If tdie1 is 0K, initialize it. */ - if (tdata->tdie1 == 0.0f) - tdata->tdie1 = tdie; - tdie_filtered = tdata->d0 * tdie + tdata->d1 * tdata->tdie1; - tdie_slope = tdie - tdie_filtered; - /* Remember the current Tdie for next time */ - tdata->tdie1 = tdie; - - /* Calculate according to TMP006 users guide. */ - tx = tdie - 298.15f; - /* s is the sensitivity */ - s = tdata->s0 * (1.0f + tdata->a1 * tx + tdata->a2 * tx * tx); - /* vos is the offset voltage */ - vos = tdata->b0 + tdata->b1 * tx + tdata->b2 * tx * tx; - /* Alg1: use Tdie FIR here */ - vx = vobj - vos + tdie_slope * tdata->ds; - /* fv is Seebeck coefficient f(vobj) */ - fv = vx + tdata->c2 * vx * vx; - - t4 = tdie * tdie * tdie * tdie + fv / s; - tobj = sqrtf(sqrtf(t4)); - - /* Alg1: apply another filter on the calculated tobj. */ - if (tdata->tobj1 == 0.0f) - tdata->tobj1 = tobj; - - tobj_filtered = tdata->e0 * tobj + tdata->e1 * tdata->tobj1; - tdata->tobj1 = tobj; - - /* return integer degrees K */ - *temp_ptr = tobj_filtered; - - return EC_SUCCESS; -} - -int tmp006_get_val(int idx, int *temp_ptr) -{ - /* - * Note: idx is a thermal sensor index, where the top N-1 bits are the - * TMP006 index and the bottom bit is (0=die, 1=remote). - */ - int tidx = idx >> 1; - struct tmp006_data_t *tdata = tmp006_data + tidx; - - if (tdata->fail & FAIL_POWER) { - /* - * Sensor isn't powered, or hasn't successfully provided data - * since being powered. Keep reporting not-powered until - * we get good data (which will clear FAIL_POWER) or there is - * an I2C error. - */ - return (tdata->fail & FAIL_I2C) ? EC_ERROR_UNKNOWN : - EC_ERROR_NOT_POWERED; - } - - /* Check the low bit to determine which temperature to read. */ - if ((idx & 0x1) == 0) - return tmp006_read_die_temp_k(tdata, temp_ptr); - else - return tmp006_read_object_temp_k(tdata, temp_ptr); -} - -/*****************************************************************************/ -/* Host commands */ - -enum ec_status tmp006_get_calibration(struct host_cmd_handler_args *args) -{ - const struct ec_params_tmp006_get_calibration *p = args->params; - struct ec_response_tmp006_get_calibration_v1 *r1 = args->response; - const struct tmp006_data_t *tdata; - - if (p->index >= TMP006_COUNT) - return EC_RES_INVALID_PARAM; - - tdata = tmp006_data + p->index; - - r1->algorithm = ALGORITHM_NUM; - r1->num_params = ALGORITHM_PARAMS; - r1->val[0] = tdata->s0; - r1->val[1] = tdata->a1; - r1->val[2] = tdata->a2; - r1->val[3] = tdata->b0; - r1->val[4] = tdata->b1; - r1->val[5] = tdata->b2; - r1->val[6] = tdata->c2; - r1->val[7] = tdata->d0; - r1->val[8] = tdata->d1; - r1->val[9] = tdata->ds; - r1->val[10] = tdata->e0; - r1->val[11] = tdata->e1; - - args->response_size = sizeof(*r1) + - r1->num_params * sizeof(r1->val[0]); - - return EC_RES_SUCCESS; -} -DECLARE_HOST_COMMAND(EC_CMD_TMP006_GET_CALIBRATION, - tmp006_get_calibration, - EC_VER_MASK(1)); - -enum ec_status tmp006_set_calibration(struct host_cmd_handler_args *args) -{ - const struct ec_params_tmp006_set_calibration_v1 *p1 = args->params; - struct tmp006_data_t *tdata; - - if (p1->index >= TMP006_COUNT) - return EC_RES_INVALID_PARAM; - - /* We only have one algorithm today */ - if (p1->algorithm != ALGORITHM_NUM || - p1->num_params != ALGORITHM_PARAMS) - return EC_RES_INVALID_PARAM; - - tdata = tmp006_data + p1->index; - - tdata->s0 = p1->val[0]; - tdata->a1 = p1->val[1]; - tdata->a2 = p1->val[2]; - tdata->b0 = p1->val[3]; - tdata->b1 = p1->val[4]; - tdata->b2 = p1->val[5]; - tdata->c2 = p1->val[6]; - tdata->d0 = p1->val[7]; - tdata->d1 = p1->val[8]; - tdata->ds = p1->val[9]; - tdata->e0 = p1->val[10]; - tdata->e1 = p1->val[11]; - - return EC_RES_SUCCESS; -} -DECLARE_HOST_COMMAND(EC_CMD_TMP006_SET_CALIBRATION, - tmp006_set_calibration, - EC_VER_MASK(1)); - -enum ec_status tmp006_get_raw(struct host_cmd_handler_args *args) -{ - const struct ec_params_tmp006_get_raw *p = args->params; - struct ec_response_tmp006_get_raw *r = args->response; - const struct tmp006_data_t *tdata; - - if (p->index >= TMP006_COUNT) - return EC_RES_INVALID_PARAM; - - tdata = tmp006_data + p->index; - - /* Vobj reg is signed int, LSB = 156.25 nV - * response units are nV */ - r->v = ((int)tdata->v_raw * 15625) / 100; - - /* Tdie reg is signed 1/128 degrees C, resolution 1/32 degrees - * response units are 1/100 degrees K */ - r->t = ((int)tdata->t_raw0 * 100) / 128 + 27315; - - args->response_size = sizeof(*r); - - return EC_RES_SUCCESS; -} -DECLARE_HOST_COMMAND(EC_CMD_TMP006_GET_RAW, - tmp006_get_raw, - EC_VER_MASK(0)); - -/*****************************************************************************/ -/* Console commands */ - -#ifdef CONFIG_CMD_TEMP_SENSOR -/** - * Print temperature info for a sensor; used by console command. - */ -static int tmp006_print(int idx) -{ - int vraw, v; - int traw, t; - int rv; - int d; - int addr_flags = tmp006_sensors[idx].addr_flags; - - - ccprintf("Debug data from %s:\n", tmp006_sensors[idx].name); - - if (!tmp006_has_power(idx)) { - ccputs("Sensor powered off.\n"); - return EC_ERROR_UNKNOWN; - } - - rv = i2c_read16(TMP006_PORT(addr_flags), - TMP006_REG(addr_flags), - TMP006_REG_MANUFACTURER_ID, &d); - if (rv) - return rv; - ccprintf(" Manufacturer ID: 0x%04x\n", d); - - rv = i2c_read16(TMP006_PORT(addr_flags), - TMP006_REG(addr_flags), - TMP006_REG_DEVICE_ID, &d); - ccprintf(" Device ID: 0x%04x\n", d); - - rv = i2c_read16(TMP006_PORT(addr_flags), - TMP006_REG(addr_flags), - TMP006_REG_CONFIG, &d); - ccprintf(" Config: 0x%04x\n", d); - - rv = i2c_read16(TMP006_PORT(addr_flags), - TMP006_REG(addr_flags), - TMP006_REG_VOBJ, &vraw); - - v = ((int)vraw * 15625) / 100; - ccprintf(" Voltage: 0x%04x = %d nV\n", vraw, v); - - rv = i2c_read16(TMP006_PORT(addr_flags), - TMP006_REG(addr_flags), - TMP006_REG_TDIE, &traw); - t = (int)traw; - ccprintf(" Temperature: 0x%04x = %d.%02d C\n", - traw, t / 128, t > 0 ? t % 128 : 128 - (t % 128)); - - return EC_SUCCESS; -} - -static int command_sensor_info(int argc, char **argv) -{ - int i; - int rv, rv1; - int a = 0, b = TMP006_COUNT; - - if (argc > 1) { - char *e = 0; - i = strtoi(argv[1], &e, 0); - if (*e || i < 0 || i >= TMP006_COUNT) - return EC_ERROR_PARAM1; - a = i; - b = i + 1; - } - - rv1 = EC_SUCCESS; - for (i = a; i < b; i++) { - rv = tmp006_print(i); - if (rv != EC_SUCCESS) - rv1 = rv; - cflush(); - } - - return rv1; -} -DECLARE_CONSOLE_COMMAND(tmp006, command_sensor_info, - "[ <index> ]", - "Print TMP006 sensors"); -#endif - -/* Disable the t6cal command until/unless we have FP support in printf */ -#if 0 -static int command_t6cal(int argc, char **argv) -{ - struct tmp006_data_t *tdata; - char *e; - int v; - int i; - - if (argc < 2) { - ccprintf("# Name S0 b0" - " b1 b2\n"); - for (i = 0; i < TMP006_COUNT; i++) { - tdata = tmp006_data + i; - ccprintf("%d %-11s" - "%7de-17 %7de-8 %7de-10 %7de-12\n", - i, tmp006_sensors[i].name, - (int)(tdata->s0 * 1e17f), - (int)(tdata->b0 * 1e8f), - (int)(tdata->b1 * 1e10f), - (int)(tdata->b2 * 1e12f)); - } - - return EC_SUCCESS; - } - - if (argc != 4) - return EC_ERROR_PARAM_COUNT; - - i = strtoi(argv[1], &e, 0); - if (*e || i < 0 || i >= TMP006_COUNT) - return EC_ERROR_PARAM1; - tdata = tmp006_data + i; - - v = strtoi(argv[3], &e, 0); - if (*e) - return EC_ERROR_PARAM3; - - if (!strcasecmp(argv[2], "s0")) - tdata->s0 = (float)v * 1e-17f; - else if (!strcasecmp(argv[2], "b0")) - tdata->b0 = (float)v * 1e-8f; - else if (!strcasecmp(argv[2], "b1")) - tdata->b1 = (float)v * 1e-10f; - else if (!strcasecmp(argv[2], "b2")) - tdata->b2 = (float)v * 1e-12f; - else - return EC_ERROR_PARAM2; - - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(t6cal, command_t6cal, - "[<index> <coeff_name> <radix>]", - "Set/print TMP006 calibration"); -#endif diff --git a/driver/temp_sensor/tmp006.h b/driver/temp_sensor/tmp006.h deleted file mode 100644 index 594dbc711a..0000000000 --- a/driver/temp_sensor/tmp006.h +++ /dev/null @@ -1,43 +0,0 @@ -/* Copyright 2014 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. - */ - -/* TMP006 temperature sensor module for Chrome EC */ - -#ifndef __CROS_EC_TMP006_H -#define __CROS_EC_TMP006_H - -/* Registers within the TMP006 chip */ -#define TMP006_REG_VOBJ 0x00 -#define TMP006_REG_TDIE 0x01 -#define TMP006_REG_CONFIG 0x02 -#define TMP006_REG_MANUFACTURER_ID 0xfe -#define TMP006_REG_DEVICE_ID 0xff - -/* I2C address components */ -#define TMP006_ADDR(PORT, REG) ((PORT << 16) + REG) -#define TMP006_PORT(ADDR) (ADDR >> 16) -#define TMP006_REG(ADDR) (ADDR & 0xffff) - -struct tmp006_t { - const char *name; - int addr_flags; /* I2C address formed by TMP006_ADDR macro. */ -}; - -/* Names and addresses of the sensors we have */ -extern const struct tmp006_t tmp006_sensors[]; - -/** - * Get the last polled value of a sensor. - * - * @param idx Index to read. The low bit in idx indicates whether - * to read die temperature or object temperature. The - * other bits serve as internal index to tmp006 module. - * @param temp_ptr Destination for temperature in K. - * - * @return EC_SUCCESS if successful, non-zero if error. - */ -int tmp006_get_val(int idx, int *temp_ptr); - -#endif /* __CROS_EC_TMP006_H */ diff --git a/driver/temp_sensor/tmp112.c b/driver/temp_sensor/tmp112.c deleted file mode 100644 index 045aca8c9c..0000000000 --- a/driver/temp_sensor/tmp112.c +++ /dev/null @@ -1,84 +0,0 @@ -/* 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. - */ - -/* TMP112 temperature sensor module for Chrome EC */ - -#include "common.h" -#include "console.h" -#include "tmp112.h" -#include "i2c.h" -#include "hooks.h" -#include "util.h" - -#define TMP112_RESOLUTION 12 -#define TMP112_SHIFT1 (16 - TMP112_RESOLUTION) -#define TMP112_SHIFT2 (TMP112_RESOLUTION - 8) - -static int temp_val_local; - -static int raw_read16(const int offset, int *data_ptr) -{ - return i2c_read16(I2C_PORT_THERMAL, TMP112_I2C_ADDR_FLAGS, - offset, data_ptr); -} - -static int raw_write16(const int offset, int data) -{ - return i2c_write16(I2C_PORT_THERMAL, TMP112_I2C_ADDR_FLAGS, - offset, data); -} - -static int get_temp(int *temp_ptr) -{ - int rv; - int temp_raw = 0; - - rv = raw_read16(TMP112_REG_TEMP, &temp_raw); - if (rv < 0) - return rv; - - *temp_ptr = (int)(int16_t)temp_raw; - return EC_SUCCESS; -} - -static inline int tmp112_reg_to_c(int16_t reg) -{ - int tmp; - - tmp = (((reg >> TMP112_SHIFT1) * 1000 ) >> TMP112_SHIFT2); - - return tmp / 1000; -} - -int tmp112_get_val(int idx, int *temp_ptr) -{ - *temp_ptr = temp_val_local; - return EC_SUCCESS; -} - -static void tmp112_poll(void) -{ - int temp_c = 0; - - if (get_temp(&temp_c) == EC_SUCCESS) - temp_val_local = C_TO_K(tmp112_reg_to_c(temp_c)); -} -DECLARE_HOOK(HOOK_SECOND, tmp112_poll, HOOK_PRIO_TEMP_SENSOR); - -static void tmp112_init(void) -{ - int tmp; - int set_mask, clr_mask; - - /* 12 bit mode */ - set_mask = (3 << 5); - - /* not oneshot mode */ - clr_mask = BIT(7); - - raw_read16(TMP112_REG_CONF, &tmp); - raw_write16(TMP112_REG_CONF, (tmp & ~clr_mask) | set_mask); -} -DECLARE_HOOK(HOOK_INIT, tmp112_init, HOOK_PRIO_DEFAULT); diff --git a/driver/temp_sensor/tmp112.h b/driver/temp_sensor/tmp112.h deleted file mode 100644 index 35f5909045..0000000000 --- a/driver/temp_sensor/tmp112.h +++ /dev/null @@ -1,29 +0,0 @@ -/* 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. - */ - -#ifndef __CROS_EC_TMP112_H -#define __CROS_EC_TMP112_H - -#include "i2c.h" - -#define TMP112_I2C_ADDR_FLAGS (0x48 | I2C_FLAG_BIG_ENDIAN) - -#define TMP112_REG_TEMP 0x00 -#define TMP112_REG_CONF 0x01 -#define TMP112_REG_HYST 0x02 -#define TMP112_REG_MAX 0x03 - -/** - * Get the last polled value of a sensor. - * - * @param idx Index to read. (Ignored) - * - * @param temp_ptr Destination for temperature in K. - * - * @return EC_SUCCESS if successful, non-zero if error. - */ -int tmp112_get_val(int idx, int *temp_ptr); - -#endif /* __CROS_EC_TMP112_H */ diff --git a/driver/temp_sensor/tmp411.c b/driver/temp_sensor/tmp411.c deleted file mode 100644 index ef22052da8..0000000000 --- a/driver/temp_sensor/tmp411.c +++ /dev/null @@ -1,330 +0,0 @@ -/* Copyright 2017 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. - */ - -/* TMP411 temperature sensor module for Chrome EC */ - -#include "common.h" -#include "console.h" -#include "tmp411.h" -#include "gpio.h" -#include "i2c.h" -#include "hooks.h" -#include "util.h" - -static int temp_val_local; -static int temp_val_remote1; -static uint8_t is_sensor_shutdown; - -/** - * Determine whether the sensor is powered. - * - * @return non-zero the tmp411 sensor is powered. - */ -static int has_power(void) -{ -#ifdef CONFIG_TEMP_SENSOR_POWER_GPIO - return gpio_get_level(CONFIG_TEMP_SENSOR_POWER_GPIO); -#else - return !is_sensor_shutdown; -#endif -} - -static int raw_read8(const int offset, int *data_ptr) -{ - return i2c_read8(I2C_PORT_THERMAL, TMP411_I2C_ADDR, offset, data_ptr); -} - -static int raw_write8(const int offset, int data) -{ - return i2c_write8(I2C_PORT_THERMAL, TMP411_I2C_ADDR, offset, data); -} - -static int get_temp(const int offset, int *temp_ptr) -{ - int rv; - int temp_raw = 0; - - rv = raw_read8(offset, &temp_raw); - if (rv < 0) - return rv; - - *temp_ptr = (int)(int8_t)temp_raw; - return EC_SUCCESS; -} - -#ifdef CONFIG_CMD_TEMP_SENSOR -static int tmp411_set_temp(const int offset, int temp) -{ - if (temp < -127 || temp > 127) - return EC_ERROR_INVAL; - - return raw_write8(offset, (uint8_t)temp); -} -#endif - -int tmp411_get_val(int idx, int *temp_ptr) -{ - if (!has_power()) - return EC_ERROR_NOT_POWERED; - - switch (idx) { - case TMP411_IDX_LOCAL: - *temp_ptr = temp_val_local; - break; - case TMP411_IDX_REMOTE1: - *temp_ptr = temp_val_remote1; - break; - default: - return EC_ERROR_UNKNOWN; - } - - return EC_SUCCESS; -} - -static int tmp411_shutdown(uint8_t want_shutdown) -{ - int ret, value; - - if (want_shutdown == is_sensor_shutdown) - return EC_SUCCESS; - - ret = raw_read8(TMP411_CONFIGURATION1_R, &value); - if (ret < 0) { - ccprintf("ERROR: Temp sensor I2C read8 error.\n"); - return ret; - } - - if (want_shutdown && !(value & TMP411_CONFIG1_RUN_L)) { - /* tmp411 is running, and want it to shutdown */ - /* CONFIG REG1 BIT6: 0=Run, 1=Shutdown */ - /* shut it down */ - value |= TMP411_CONFIG1_RUN_L; - ret = raw_write8(TMP411_CONFIGURATION1_R, value); - } else if (!want_shutdown && (value & TMP411_CONFIG1_RUN_L)) { - /* tmp411 is shutdown, and want turn it on */ - value &= ~TMP411_CONFIG1_RUN_L; - ret = raw_write8(TMP411_CONFIGURATION1_R, value); - } - /* else, the current setting is exactly what you want */ - - is_sensor_shutdown = want_shutdown; - return ret; -} - -static int tmp411_set_therm_mode(void) -{ - int ret = 0; - int data = 0; - - ret = raw_read8(TMP411_CONFIGURATION1_R, &data); - if (ret) - return EC_ERROR_UNKNOWN; - - data |= TMP411_CONFIG1_MODE; - ret = raw_write8(TMP411_CONFIGURATION1_W, data); - if (ret) - return EC_ERROR_UNKNOWN; - - return EC_SUCCESS; -} - -int tmp411_set_therm_limit(int channel, int limit_c, int hysteresis) -{ - int ret = 0; - int reg = 0; - - if (channel >= TMP411_CHANNEL_COUNT) - return EC_ERROR_INVAL; - - if (hysteresis > TMP411_HYSTERESIS_HIGH_LIMIT || - hysteresis < TMP411_HYSTERESIS_LOW_LIMIT) - return EC_ERROR_INVAL; - - /* hysteresis must be less than high limit */ - if (hysteresis > limit_c) - return EC_ERROR_INVAL; - - if (tmp411_set_therm_mode() != EC_SUCCESS) - return EC_ERROR_UNKNOWN; - - switch (channel) { - case TMP411_CHANNEL_LOCAL: - reg = TMP411_LOCAL_HIGH_LIMIT_W; - break; - case TMP411_CHANNEL_REMOTE1: - reg = TMP411_REMOTE1_HIGH_LIMIT_W; - break; - } - - ret = raw_write8(reg, limit_c); - if (ret) - return EC_ERROR_UNKNOWN; - - ret = raw_write8(TMP411_THERM_HYSTERESIS, hysteresis); - if (ret) - return EC_ERROR_UNKNOWN; - - return EC_SUCCESS; -} - -static void tmp411_temp_sensor_poll(void) -{ - int temp_c; - - if (!has_power()) - return; - - if (get_temp(TMP411_LOCAL, &temp_c) == EC_SUCCESS) - temp_val_local = C_TO_K(temp_c); - - if (get_temp(TMP411_REMOTE1, &temp_c) == EC_SUCCESS) - temp_val_remote1 = C_TO_K(temp_c); - -} -DECLARE_HOOK(HOOK_SECOND, tmp411_temp_sensor_poll, HOOK_PRIO_TEMP_SENSOR); - -#ifdef CONFIG_CMD_TEMP_SENSOR -static void print_temps( - const char *name, - const int tmp411_temp_reg, - const int tmp411_therm_limit_reg, - const int tmp411_high_limit_reg, - const int tmp411_low_limit_reg) -{ - int value; - - if (!has_power()) { - ccprintf(" TMP411 is shutdown\n"); - return; - } - - ccprintf("%s:\n", name); - - if (get_temp(tmp411_temp_reg, &value) == EC_SUCCESS) - ccprintf(" Temp %3dC\n", value); - - if (get_temp(tmp411_therm_limit_reg, &value) == EC_SUCCESS) - ccprintf(" Therm Trip %3dC\n", value); - - if (get_temp(tmp411_high_limit_reg, &value) == EC_SUCCESS) - ccprintf(" High Alarm %3dC\n", value); - - if (get_temp(tmp411_low_limit_reg, &value) == EC_SUCCESS) - ccprintf(" Low Alarm %3dC\n", value); -} - -static int print_status(void) -{ - int value; - - print_temps("Local", TMP411_LOCAL, - TMP411_LOCAL_THERM_LIMIT, - TMP411_LOCAL_HIGH_LIMIT_R, - TMP411_LOCAL_LOW_LIMIT_R); - - print_temps("Remote1", TMP411_REMOTE1, - TMP411_REMOTE1_THERM_LIMIT, - TMP411_REMOTE1_HIGH_LIMIT_R, - TMP411_REMOTE1_LOW_LIMIT_R); - - ccprintf("\n"); - - if (raw_read8(TMP411_STATUS_R, &value) == EC_SUCCESS) - ccprintf("STATUS: %pb\n", BINARY_VALUE(value, 8)); - - if (raw_read8(TMP411_CONFIGURATION1_R, &value) == EC_SUCCESS) - ccprintf("CONFIG1: %pb\n", BINARY_VALUE(value, 8)); - - return EC_SUCCESS; -} - -static int command_tmp411(int argc, char **argv) -{ - char *command; - char *e; - char *power; - int data; - int offset; - int rv; - - /* handle "power" command before checking the power status. */ - if ((argc == 3) && !strcasecmp(argv[1], "power")) { - power = argv[2]; - if (!strncasecmp(power, "on", sizeof("on"))) { - rv = tmp411_set_power(TMP411_POWER_ON); - if (!rv) - print_status(); - } else if (!strncasecmp(power, "off", sizeof("off"))) - rv = tmp411_set_power(TMP411_POWER_OFF); - else - return EC_ERROR_PARAM2; - ccprintf("Set TMP411 %s\n", power); - return rv; - } - - if (!has_power()) { - ccprintf("ERROR: Temp sensor not powered.\n"); - return EC_ERROR_NOT_POWERED; - } - - /* If no args just print status */ - if (argc == 1) - return print_status(); - - if (argc < 3) - return EC_ERROR_PARAM_COUNT; - - command = argv[1]; - offset = strtoi(argv[2], &e, 0); - if (*e || offset < 0 || offset > 255) - return EC_ERROR_PARAM2; - - if (!strcasecmp(command, "getbyte")) { - rv = raw_read8(offset, &data); - if (rv < 0) - return rv; - ccprintf("Byte at offset 0x%02x is %pb\n", - offset, BINARY_VALUE(data, 8)); - return rv; - } - - /* Remaining commands are "tmp411 set-command offset data" */ - if (argc != 4) - return EC_ERROR_PARAM_COUNT; - - data = strtoi(argv[3], &e, 0); - if (*e) - return EC_ERROR_PARAM3; - - if (!strcasecmp(command, "settemp")) { - ccprintf("Setting 0x%02x to %dC\n", offset, data); - rv = tmp411_set_temp(offset, data); - } else if (!strcasecmp(command, "setbyte")) { - ccprintf("Setting 0x%02x to 0x%02x\n", offset, data); - rv = raw_write8(offset, data); - } else - return EC_ERROR_PARAM1; - - return rv; -} -DECLARE_CONSOLE_COMMAND(tmp411, command_tmp411, - "[settemp|setbyte <offset> <value>] or [getbyte <offset>] or" - "[power <on|off>]. " - "Temps in Celsius.", - "Print tmp411 temp sensor status or set parameters."); -#endif - -int tmp411_set_power(enum tmp411_power_state power_on) -{ -#ifndef CONFIG_TEMP_SENSOR_POWER_GPIO - uint8_t shutdown = (power_on == TMP411_POWER_OFF) ? 1 : 0; - - return tmp411_shutdown(shutdown); -#else - gpio_set_level(CONFIG_TEMP_SENSOR_POWER_GPIO, power_on); - return EC_SUCCESS; -#endif -} - diff --git a/driver/temp_sensor/tmp411.h b/driver/temp_sensor/tmp411.h deleted file mode 100644 index ef1b23278c..0000000000 --- a/driver/temp_sensor/tmp411.h +++ /dev/null @@ -1,140 +0,0 @@ -/* Copyright 2017 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. - */ - -/* TMP411 temperature sensor module for Chrome EC */ - -#ifndef __CROS_EC_TMP411_H -#define __CROS_EC_TMP411_H - -#define TMP411_I2C_ADDR_FLAGS 0x4C - -#define TMP411_IDX_LOCAL 0 -#define TMP411_IDX_REMOTE1 1 -#define TMP411_IDX_REMOTE2 2 - -/* Chip-specific registers */ -#define TMP411_LOCAL 0x00 -#define TMP411_REMOTE1 0x01 -#define TMP411_STATUS_R 0x02 -#define TMP411_CONFIGURATION1_R 0x03 -#define TMP411_CONVERSION_RATE_R 0x04 -#define TMP411_LOCAL_HIGH_LIMIT_R 0x05 -#define TMP411_LOCAL_LOW_LIMIT_R 0x06 -#define TMP411_REMOTE1_HIGH_LIMIT_R 0x07 -#define TMP411_REMOTE1_LOW_LIMIT_R 0x08 -#define TMP411_CONFIGURATION1_W 0x09 -#define TMP411_CONVERSION_RATE_W 0x0a -#define TMP411_LOCAL_HIGH_LIMIT_W 0x0b -#define TMP411_LOCAL_LOW_LIMIT_W 0x0c -#define TMP411_REMOTE1_HIGH_LIMIT_W 0x0d -#define TMP411_REMOTE1_LOW_LIMIT_W 0x0e -#define TMP411_ONESHOT 0x0f -#define TMP411_REMOTE1_EXTD 0x10 -#define TMP411_REMOTE1_HIGH_LIMIT_EXTD 0x13 -#define TMP411_REMOTE1_LOW_LIMIT_EXTD 0x14 -#define TMP411_REMOTE2_HIGH_LIMIT_R 0x15 -#define TMP411_REMOTE2_HIGH_LIMIT_W 0x15 -#define TMP411_REMOTE2_LOW_LIMIT_R 0x16 -#define TMP411_REMOTE2_LOW_LIMIT_W 0x16 -#define TMP411_REMOTE2_HIGH_LIMIT_EXTD 0x17 -#define TMP411_REMOTE2_LOW_LIMIT_EXTD 0x18 -#define TMP411_REMOTE1_THERM_LIMIT 0x19 -#define TMP411_REMOTE2_THERM_LIMIT 0x1a -#define TMP411_STATUS_FAULT 0x1b -#define TMP411_CHANNEL_MASK 0x1f -#define TMP411_LOCAL_THERM_LIMIT 0x20 -#define TMP411_THERM_HYSTERESIS 0x21 -#define TMP411_CONSECUTIVE_ALERT 0x22 -#define TMP411_REMOTE2 0x23 -#define TMP411_REMOTE2_EXTD 0x24 -#define TMP411_BETA_RANGE_CH1 0x25 -#define TMP411_BETA_RANGE_CH2 0x26 -#define TMP411_NFACTOR_REMOTE1 0x27 -#define TMP411_NFACTOR_REMOTE2 0x28 -#define TMP411_LOCAL_EXTD 0x29 -#define TMP411_STATUS_LIMIT_HIGH 0x35 -#define TMP411_STATUS_LIMIT_LOW 0x36 -#define TMP411_STATUS_THERM 0x37 -#define TMP411_RESET_W 0xfc -#define TMP411_MANUFACTURER_ID 0xfe -#define TMP411_DEVICE_ID 0xff - -#define TMP411A_DEVICE_ID_VAL 0x12 -#define TMP411B_DEVICE_ID_VAL 0x13 -#define TMP411C_DEVICE_ID_VAL 0x10 -#define TMP411d_DEVICE_ID_VAL 0x12 - -/* Config register bits */ -#define TMP411_CONFIG1_TEMP_RANGE BIT(2) -/* TMP411_CONFIG1_MODE bit is use to enable THERM mode */ -#define TMP411_CONFIG1_MODE BIT(5) -#define TMP411_CONFIG1_RUN_L BIT(6) -#define TMP411_CONFIG1_ALERT_MASK_L BIT(7) - -/* Status register bits */ -#define TMP411_STATUS_TEMP_THERM_ALARM BIT(1) -#define TMP411_STATUS_OPEN BIT(2) -#define TMP411_STATUS_TEMP_LOW_ALARM BIT(3) -#define TMP411_STATUS_TEMP_HIGH_ALARM BIT(4) -#define TMP411_STATUS_LOCAL_TEMP_LOW_ALARM BIT(5) -#define TMP411_STATUS_LOCAL_TEMP_HIGH_ALARM BIT(6) -#define TMP411_STATUS_BUSY BIT(7) - -/* Limits */ -#define TMP411_HYSTERESIS_HIGH_LIMIT 255 -#define TMP411_HYSTERESIS_LOW_LIMIT 0 - -enum tmp411_power_state { - TMP411_POWER_OFF = 0, - TMP411_POWER_ON, - TMP411_POWER_COUNT -}; - -enum tmp411_channel_id { - TMP411_CHANNEL_LOCAL, - TMP411_CHANNEL_REMOTE1, - - TMP411_CHANNEL_COUNT -}; - -/** - * Get the last polled value of a sensor. - * - * @param idx Index to read. Idx indicates whether to read die - * temperature or external temperature. - * @param temp_ptr Destination for temperature in K. - * - * @return EC_SUCCESS if successful, non-zero if error. - */ -int tmp411_get_val(int idx, int *temp_ptr); - -/** - * Power control function of tmp411 temperature sensor. - * - * @param power_on TMP411_POWER_ON: turn tmp411 sensor on. - * TMP411_POWER_OFF: shut tmp411 sensor down. - * - * @return EC_SUCCESS if successful, non-zero if error. - */ -int tmp411_set_power(enum tmp411_power_state power_on); - -/* - * Set TMP411 ALERT#/THERM2# pin to THERM mode, and give a limit - * for a specific channel. - * - * @param channel specific a channel - * - * @param limit_c High limit temperature, default: 85C - * - * @param hysteresis Hysteresis temperature, default: 10C - * All channels share the same hysteresis - * - * In THERM mode, ALERT# pin will trigger(Low) by itself when any - * channel's temperature is greater( >= )than channel's limit_c, - * and release(High) by itself when channel's temperature is lower - * than (limit_c - hysteresis) - */ -int tmp411_set_therm_limit(int channel, int limit_c, int hysteresis); -#endif /* __CROS_EC_TMP411_H */ diff --git a/driver/temp_sensor/tmp432.c b/driver/temp_sensor/tmp432.c deleted file mode 100644 index 9f76e74660..0000000000 --- a/driver/temp_sensor/tmp432.c +++ /dev/null @@ -1,395 +0,0 @@ -/* Copyright 2013 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. - */ - -/* TMP432 temperature sensor module for Chrome EC */ - -#include "common.h" -#include "console.h" -#include "tmp432.h" -#include "gpio.h" -#include "i2c.h" -#include "hooks.h" -#include "util.h" - -static int temp_val_local; -static int temp_val_remote1; -static int temp_val_remote2; -static uint8_t is_sensor_shutdown; -static int fake_temp[TMP432_IDX_COUNT] = {-1, -1, -1}; - -/** - * Determine whether the sensor is powered. - * - * @return non-zero the tmp432 sensor is powered. - */ -static int has_power(void) -{ -#ifdef CONFIG_TEMP_SENSOR_POWER_GPIO - return gpio_get_level(CONFIG_TEMP_SENSOR_POWER_GPIO); -#else - return !is_sensor_shutdown; -#endif -} - -static int raw_read8(const int offset, int *data_ptr) -{ - return i2c_read8(I2C_PORT_THERMAL, TMP432_I2C_ADDR_FLAGS, - offset, data_ptr); -} - -static int raw_write8(const int offset, int data) -{ - return i2c_write8(I2C_PORT_THERMAL, TMP432_I2C_ADDR_FLAGS, - offset, data); -} - -static int get_temp(const int offset, int *temp_ptr) -{ - int rv; - int temp_raw = 0; - - rv = raw_read8(offset, &temp_raw); - if (rv < 0) - return rv; - - *temp_ptr = (int)(int8_t)temp_raw; - return EC_SUCCESS; -} - -#ifdef CONFIG_CMD_TEMP_SENSOR -static int tmp432_set_temp(const int offset, int temp) -{ - if (temp < -127 || temp > 127) - return EC_ERROR_INVAL; - - return raw_write8(offset, (uint8_t)temp); -} -#endif - -int tmp432_get_val(int idx, int *temp_ptr) -{ - if (!has_power()) - return EC_ERROR_NOT_POWERED; - - switch (idx) { - case TMP432_IDX_LOCAL: - *temp_ptr = temp_val_local; - break; - case TMP432_IDX_REMOTE1: - *temp_ptr = temp_val_remote1; - break; - case TMP432_IDX_REMOTE2: - *temp_ptr = temp_val_remote2; - break; - default: - return EC_ERROR_UNKNOWN; - } - - return EC_SUCCESS; -} - -static int tmp432_shutdown(uint8_t want_shutdown) -{ - int ret, value; - - if (want_shutdown == is_sensor_shutdown) - return EC_SUCCESS; - - ret = raw_read8(TMP432_CONFIGURATION1_R, &value); - if (ret < 0) { - ccprintf("ERROR: Temp sensor I2C read8 error.\n"); - return ret; - } - - if (want_shutdown && !(value & TMP432_CONFIG1_RUN_L)) { - /* tmp432 is running, and want it to shutdown */ - /* CONFIG REG1 BIT6: 0=Run, 1=Shutdown */ - /* shut it down */ - value |= TMP432_CONFIG1_RUN_L; - ret = raw_write8(TMP432_CONFIGURATION1_R, value); - } else if (!want_shutdown && (value & TMP432_CONFIG1_RUN_L)) { - /* tmp432 is shutdown, and want turn it on */ - value &= ~TMP432_CONFIG1_RUN_L; - ret = raw_write8(TMP432_CONFIGURATION1_R, value); - } - /* else, the current setting is exactly what you want */ - - is_sensor_shutdown = want_shutdown; - return ret; -} - -static int tmp432_set_therm_mode(void) -{ - int ret = 0; - int data = 0; - - ret = raw_read8(TMP432_CONFIGURATION1_R, &data); - if (ret) - return EC_ERROR_UNKNOWN; - - data |= TMP432_CONFIG1_MODE; - ret = raw_write8(TMP432_CONFIGURATION1_W, data); - if (ret) - return EC_ERROR_UNKNOWN; - - return EC_SUCCESS; -} - -int tmp432_set_therm_limit(int channel, int limit_c, int hysteresis) -{ - int ret = 0; - int reg = 0; - - if (channel >= TMP432_CHANNEL_COUNT) - return EC_ERROR_INVAL; - - if (hysteresis > TMP432_HYSTERESIS_HIGH_LIMIT || - hysteresis < TMP432_HYSTERESIS_LOW_LIMIT) - return EC_ERROR_INVAL; - - /* hysteresis must be less than high limit */ - if (hysteresis > limit_c) - return EC_ERROR_INVAL; - - if (tmp432_set_therm_mode() != EC_SUCCESS) - return EC_ERROR_UNKNOWN; - - switch (channel) { - case TMP432_CHANNEL_LOCAL: - reg = TMP432_LOCAL_HIGH_LIMIT_W; - break; - case TMP432_CHANNEL_REMOTE1: - reg = TMP432_REMOTE1_HIGH_LIMIT_W; - break; - case TMP432_CHANNEL_REMOTE2: - reg = TMP432_REMOTE2_HIGH_LIMIT_W; - break; - } - - ret = raw_write8(reg, limit_c); - if (ret) - return EC_ERROR_UNKNOWN; - - ret = raw_write8(TMP432_THERM_HYSTERESIS, hysteresis); - if (ret) - return EC_ERROR_UNKNOWN; - - return EC_SUCCESS; -} - -static void temp_sensor_poll(void) -{ - int temp_c; - - if (!has_power()) - return; - - if (fake_temp[TMP432_IDX_LOCAL] != -1) { - temp_val_local = C_TO_K(fake_temp[TMP432_IDX_LOCAL]); - } else { - if (get_temp(TMP432_LOCAL, &temp_c) == EC_SUCCESS) - temp_val_local = C_TO_K(temp_c); - /* else: Keep previous value when it fails */ - } - - if (fake_temp[TMP432_IDX_REMOTE1] != -1) { - temp_val_remote1 = C_TO_K(fake_temp[TMP432_IDX_REMOTE1]); - } else { - if (get_temp(TMP432_REMOTE1, &temp_c) == EC_SUCCESS) - temp_val_remote1 = C_TO_K(temp_c); - /* else: Keep previous value when it fails */ - } - - if (fake_temp[TMP432_IDX_REMOTE2] != -1) { - temp_val_remote2 = C_TO_K(fake_temp[TMP432_IDX_REMOTE2]); - } else { - if (get_temp(TMP432_REMOTE2, &temp_c) == EC_SUCCESS) - temp_val_remote2 = C_TO_K(temp_c); - /* else: Keep previous value when it fails */ - } -} -DECLARE_HOOK(HOOK_SECOND, temp_sensor_poll, HOOK_PRIO_TEMP_SENSOR); - -#ifdef CONFIG_CMD_TEMP_SENSOR -static int tmp432_set_fake_temp(int index, int degree_c) -{ - if ((index < 0) || (index >= TMP432_IDX_COUNT)) - return EC_ERROR_INVAL; - - fake_temp[index] = degree_c; - ccprintf("New degree will be updated 1 sec later\n\n"); - - return EC_SUCCESS; -} - -static void print_temps( - const char *name, - const int tmp432_temp_reg, - const int tmp432_therm_limit_reg, - const int tmp432_high_limit_reg, - const int tmp432_low_limit_reg) -{ - int value; - - if (!has_power()) { - ccprintf(" TMP432 is shutdown\n"); - return; - } - - ccprintf("%s:\n", name); - - if (get_temp(tmp432_temp_reg, &value) == EC_SUCCESS) - ccprintf(" Temp %3dC\n", value); - - if (get_temp(tmp432_therm_limit_reg, &value) == EC_SUCCESS) - ccprintf(" Therm Trip %3dC\n", value); - - if (get_temp(tmp432_high_limit_reg, &value) == EC_SUCCESS) - ccprintf(" High Alarm %3dC\n", value); - - if (get_temp(tmp432_low_limit_reg, &value) == EC_SUCCESS) - ccprintf(" Low Alarm %3dC\n", value); -} - -static int print_status(void) -{ - int value, i; - - print_temps("Local", TMP432_LOCAL, - TMP432_LOCAL_THERM_LIMIT, - TMP432_LOCAL_HIGH_LIMIT_R, - TMP432_LOCAL_LOW_LIMIT_R); - - print_temps("Remote1", TMP432_REMOTE1, - TMP432_REMOTE1_THERM_LIMIT, - TMP432_REMOTE1_HIGH_LIMIT_R, - TMP432_REMOTE1_LOW_LIMIT_R); - - print_temps("Remote2", TMP432_REMOTE2, - TMP432_REMOTE2_THERM_LIMIT, - TMP432_REMOTE2_HIGH_LIMIT_R, - TMP432_REMOTE2_LOW_LIMIT_R); - - ccprintf("\n"); - - for (i = 0; i < TMP432_IDX_COUNT; ++i) { - ccprintf("fake temperature[%d]= ", i); - if (fake_temp[i] == -1) { - ccprintf("Not overridden\n"); - continue; - } - - if (tmp432_get_val(i, &value) == EC_SUCCESS) - ccprintf("%d C or %d K\n", (value - 273), value); - else - ccprintf("Access error\n"); - } - - ccprintf("\n"); - - if (raw_read8(TMP432_STATUS, &value) == EC_SUCCESS) - ccprintf("STATUS: %pb\n", BINARY_VALUE(value, 8)); - - if (raw_read8(TMP432_CONFIGURATION1_R, &value) == EC_SUCCESS) - ccprintf("CONFIG1: %pb\n", BINARY_VALUE(value, 8)); - - if (raw_read8(TMP432_CONFIGURATION2_R, &value) == EC_SUCCESS) - ccprintf("CONFIG2: %pb\n", BINARY_VALUE(value, 8)); - - return EC_SUCCESS; -} - -static int command_tmp432(int argc, char **argv) -{ - char *command; - char *e; - char *power; - int data; - int offset; - int rv; - - /* handle "power" command before checking the power status. */ - if ((argc == 3) && !strcasecmp(argv[1], "power")) { - power = argv[2]; - if (!strncasecmp(power, "on", sizeof("on"))) { - rv = tmp432_set_power(TMP432_POWER_ON); - if (!rv) - print_status(); - } - else if (!strncasecmp(power, "off", sizeof("off"))) - rv = tmp432_set_power(TMP432_POWER_OFF); - else - return EC_ERROR_PARAM2; - ccprintf("Set TMP432 %s\n", power); - return rv; - } - - if (!has_power()) { - ccprintf("ERROR: Temp sensor not powered.\n"); - return EC_ERROR_NOT_POWERED; - } - - /* If no args just print status */ - if (argc == 1) - return print_status(); - - if (argc < 3) - return EC_ERROR_PARAM_COUNT; - - command = argv[1]; - offset = strtoi(argv[2], &e, 0); - if (*e || offset < 0 || offset > 255) - return EC_ERROR_PARAM2; - - if (!strcasecmp(command, "getbyte")) { - rv = raw_read8(offset, &data); - if (rv < 0) - return rv; - ccprintf("Byte at offset 0x%02x is %pb\n", - offset, BINARY_VALUE(data, 8)); - return rv; - } - - /* Remaining commands are "tmp432 set-command offset data" */ - if (argc != 4) - return EC_ERROR_PARAM_COUNT; - - data = strtoi(argv[3], &e, 0); - if (*e) - return EC_ERROR_PARAM3; - - if (!strcasecmp(command, "settemp")) { - ccprintf("Setting 0x%02x to %dC\n", offset, data); - rv = tmp432_set_temp(offset, data); - } else if (!strcasecmp(command, "setbyte")) { - ccprintf("Setting 0x%02x to 0x%02x\n", offset, data); - rv = raw_write8(offset, data); - } else if (!strcasecmp(command, "fake")) { - ccprintf("Hook temperature\n"); - rv = tmp432_set_fake_temp(offset, data); - print_status(); - } else - return EC_ERROR_PARAM1; - - return rv; -} -DECLARE_CONSOLE_COMMAND(tmp432, command_tmp432, - "[settemp|setbyte <offset> <value>] or [getbyte <offset>] or" - "[fake <index> <value>] or [power <on|off>]. " - "Temps in Celsius.", - "Print tmp432 temp sensor status or set parameters."); -#endif - -int tmp432_set_power(enum tmp432_power_state power_on) -{ -#ifndef CONFIG_TEMP_SENSOR_POWER_GPIO - uint8_t shutdown = (power_on == TMP432_POWER_OFF) ? 1 : 0; - return tmp432_shutdown(shutdown); -#else - gpio_set_level(CONFIG_TEMP_SENSOR_POWER_GPIO, power_on); - return EC_SUCCESS; -#endif -} - diff --git a/driver/temp_sensor/tmp432.h b/driver/temp_sensor/tmp432.h deleted file mode 100644 index e58e39a4a0..0000000000 --- a/driver/temp_sensor/tmp432.h +++ /dev/null @@ -1,143 +0,0 @@ -/* Copyright 2013 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. - */ - -/* TMP432 temperature sensor module for Chrome EC */ - -#ifndef __CROS_EC_TMP432_H -#define __CROS_EC_TMP432_H - -#define TMP432_I2C_ADDR_FLAGS 0x4C - -#define TMP432_IDX_LOCAL 0 -#define TMP432_IDX_REMOTE1 1 -#define TMP432_IDX_REMOTE2 2 -#define TMP432_IDX_COUNT 3 - -/* Chip-specific registers */ -#define TMP432_LOCAL 0x00 -#define TMP432_REMOTE1 0x01 -#define TMP432_STATUS 0x02 -#define TMP432_CONFIGURATION1_R 0x03 -#define TMP432_CONVERSION_RATE_R 0x04 -#define TMP432_LOCAL_HIGH_LIMIT_R 0x05 -#define TMP432_LOCAL_LOW_LIMIT_R 0x06 -#define TMP432_REMOTE1_HIGH_LIMIT_R 0x07 -#define TMP432_REMOTE1_LOW_LIMIT_R 0x08 -#define TMP432_CONFIGURATION1_W 0x09 -#define TMP432_CONVERSION_RATE_W 0x0a -#define TMP432_LOCAL_HIGH_LIMIT_W 0x0b -#define TMP432_LOCAL_LOW_LIMIT_W 0x0c -#define TMP432_REMOTE1_HIGH_LIMIT_W 0x0d -#define TMP432_REMOTE1_LOW_LIMIT_W 0x0e -#define TMP432_ONESHOT 0x0f -#define TMP432_REMOTE1_EXTD 0x10 -#define TMP432_REMOTE1_HIGH_LIMIT_EXTD 0x13 -#define TMP432_REMOTE1_LOW_LIMIT_EXTD 0x14 -#define TMP432_REMOTE2_HIGH_LIMIT_R 0x15 -#define TMP432_REMOTE2_HIGH_LIMIT_W 0x15 -#define TMP432_REMOTE2_LOW_LIMIT_R 0x16 -#define TMP432_REMOTE2_LOW_LIMIT_W 0x16 -#define TMP432_REMOTE2_HIGH_LIMIT_EXTD 0x17 -#define TMP432_REMOTE2_LOW_LIMIT_EXTD 0x18 -#define TMP432_REMOTE1_THERM_LIMIT 0x19 -#define TMP432_REMOTE2_THERM_LIMIT 0x1a -#define TMP432_STATUS_FAULT 0x1b -#define TMP432_CHANNEL_MASK 0x1f -#define TMP432_LOCAL_THERM_LIMIT 0x20 -#define TMP432_THERM_HYSTERESIS 0x21 -#define TMP432_CONSECUTIVE_ALERT 0x22 -#define TMP432_REMOTE2 0x23 -#define TMP432_REMOTE2_EXTD 0x24 -#define TMP432_BETA_RANGE_CH1 0x25 -#define TMP432_BETA_RANGE_CH2 0x26 -#define TMP432_NFACTOR_REMOTE1 0x27 -#define TMP432_NFACTOR_REMOTE2 0x28 -#define TMP432_LOCAL_EXTD 0x29 -#define TMP432_STATUS_LIMIT_HIGH 0x35 -#define TMP432_STATUS_LIMIT_LOW 0x36 -#define TMP432_STATUS_THERM 0x37 -#define TMP432_LOCAL_HIGH_LIMIT_EXTD 0x3d -#define TMP432_LOCAL_LOW_LIMIT_EXTD 0x3e -#define TMP432_CONFIGURATION2_R 0x3f -#define TMP432_CONFIGURATION2_W 0x3f -#define TMP432_RESET_W 0xfc -#define TMP432_DEVICE_ID 0xfd -#define TMP432_MANUFACTURER_ID 0xfe - -/* Config register bits */ -#define TMP432_CONFIG1_TEMP_RANGE BIT(2) -/* TMP432_CONFIG1_MODE bit is use to enable THERM mode */ -#define TMP432_CONFIG1_MODE BIT(5) -#define TMP432_CONFIG1_RUN_L BIT(6) -#define TMP432_CONFIG1_ALERT_MASK_L BIT(7) -#define TMP432_CONFIG2_RESISTANCE_CORRECTION BIT(2) -#define TMP432_CONFIG2_LOCAL_ENABLE BIT(3) -#define TMP432_CONFIG2_REMOTE1_ENABLE BIT(4) -#define TMP432_CONFIG2_REMOTE2_ENABLE BIT(5) - -/* Status register bits */ -#define TMP432_STATUS_TEMP_THERM_ALARM BIT(1) -#define TMP432_STATUS_OPEN BIT(2) -#define TMP432_STATUS_TEMP_LOW_ALARM BIT(3) -#define TMP432_STATUS_TEMP_HIGH_ALARM BIT(4) -#define TMP432_STATUS_BUSY BIT(7) - -/* Limintaions */ -#define TMP432_HYSTERESIS_HIGH_LIMIT 255 -#define TMP432_HYSTERESIS_LOW_LIMIT 0 - -enum tmp432_power_state { - TMP432_POWER_OFF = 0, - TMP432_POWER_ON, - TMP432_POWER_COUNT -}; - -enum tmp432_channel_id { - TMP432_CHANNEL_LOCAL, - TMP432_CHANNEL_REMOTE1, - TMP432_CHANNEL_REMOTE2, - - TMP432_CHANNEL_COUNT -}; - -/** - * Get the last polled value of a sensor. - * - * @param idx Index to read. Idx indicates whether to read die - * temperature or external temperature. - * @param temp_ptr Destination for temperature in K. - * - * @return EC_SUCCESS if successful, non-zero if error. - */ -int tmp432_get_val(int idx, int *temp_ptr); - -/** - * Power control function of tmp432 temperature sensor. - * - * @param power_on TMP432_POWER_ON: turn tmp432 sensor on. - * TMP432_POWER_OFF: shut tmp432 sensor down. - * - * @return EC_SUCCESS if successful, non-zero if error. - */ -int tmp432_set_power(enum tmp432_power_state power_on); - -/* - * Set TMP432 ALERT#/THERM2# pin to THERM mode, and give a limit - * for a specific channel. - * - * @param channel specific a channel - * - * @param limit_c High limit temperature, default: 85C - * - * @param hysteresis Hysteresis temperature, default: 10C - * All channels share the same hysteresis - * - * In THERM mode, ALERT# pin will trigger(Low) by itself when any - * channel's temperature is greater( >= )than channel's limit_c, - * and release(High) by itself when channel's temperature is lower - * than (limit_c - hysteresis) - */ -int tmp432_set_therm_limit(int channel, int limit_c, int hysteresis); -#endif /* __CROS_EC_TMP432_H */ diff --git a/driver/temp_sensor/tmp468.c b/driver/temp_sensor/tmp468.c deleted file mode 100644 index 46e77ca696..0000000000 --- a/driver/temp_sensor/tmp468.c +++ /dev/null @@ -1,101 +0,0 @@ -/* Copyright 2018 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. - */ - -/* TMP468 temperature sensor module for Chrome EC */ - -#include "common.h" -#include "console.h" -#include "tmp432.h" -#include "gpio.h" -#include "i2c.h" -#include "hooks.h" -#include "util.h" - -#include "tmp468.h" - - -static int fake_temp[TMP468_CHANNEL_COUNT] = {-1, -1, -1, -1, -1, -1, -1 , -1, -1}; -static int temp_val[TMP468_CHANNEL_COUNT] = {0, 0, 0, 0, 0, 0, 0 , 0, 0}; -static uint8_t is_sensor_shutdown; - -static int has_power(void) -{ - return !is_sensor_shutdown; -} - -static int raw_read16(const int offset, int *data_ptr) -{ - return i2c_read16(I2C_PORT_THERMAL, TMP468_I2C_ADDR_FLAGS, - offset, data_ptr); -} - -static int raw_write16(const int offset, int data_ptr) -{ - return i2c_write16(I2C_PORT_THERMAL, TMP468_I2C_ADDR_FLAGS, - offset, data_ptr); -} - -static int tmp468_shutdown(uint8_t want_shutdown) -{ - int ret, value; - - if (want_shutdown == is_sensor_shutdown) - return EC_SUCCESS; - - ret = raw_read16(TMP468_CONFIGURATION, &value); - if (ret < 0) { - ccprintf("ERROR: Temp sensor I2C read16 error.\n"); - return ret; - } - - if (want_shutdown) - value |= TMP468_SHUTDOWN; - else - value &= ~TMP468_SHUTDOWN; - - ret = raw_write16(TMP468_CONFIGURATION, value); - if (ret == EC_SUCCESS) - is_sensor_shutdown = want_shutdown; - - return EC_SUCCESS; -} - -int tmp468_get_val(int idx, int *temp_ptr) -{ - if(!has_power()) - return EC_ERROR_NOT_POWERED; - - if (idx < TMP468_CHANNEL_COUNT) { - *temp_ptr = C_TO_K(temp_val[idx]); - return EC_SUCCESS; - } - - return EC_ERROR_INVAL; -} - -static void temp_sensor_poll(void) -{ - int i, ret; - - if (!has_power()) - return; - - for (i = 0; i < TMP468_CHANNEL_COUNT; i++) - if (fake_temp[i] != -1) { - temp_val[i] = fake_temp[i]; - } else { - ret = raw_read16(TMP468_LOCAL + i, &temp_val[i]); - if (ret < 0) - return; - temp_val[i] >>= TMP468_SHIFT1; - } -} -DECLARE_HOOK(HOOK_SECOND, temp_sensor_poll, HOOK_PRIO_TEMP_SENSOR); - -int tmp468_set_power(enum tmp468_power_state power_on) -{ - uint8_t shutdown = (power_on == TMP468_POWER_OFF) ? 1 : 0; - return tmp468_shutdown(shutdown); -} diff --git a/driver/temp_sensor/tmp468.h b/driver/temp_sensor/tmp468.h deleted file mode 100644 index 59fbd20477..0000000000 --- a/driver/temp_sensor/tmp468.h +++ /dev/null @@ -1,126 +0,0 @@ -/* Copyright 2018 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. - */ - -/* TMP468 temperature sensor module for Chrome EC */ - -#ifndef __CROS_EC_TMP468_H -#define __CROS_EC_TMP468_H - -#define TMP468_I2C_ADDR_FLAGS (0x48 | I2C_FLAG_BIG_ENDIAN) -#define TMP468_SHIFT1 7 - -#define TMP468_LOCAL 0x00 -#define TMP468_REMOTE1 0x01 -#define TMP468_REMOTE2 0x02 -#define TMP468_REMOTE3 0x03 -#define TMP468_REMOTE4 0x04 -#define TMP468_REMOTE5 0x05 -#define TMP468_REMOTE6 0x06 -#define TMP468_REMOTE7 0x07 -#define TMP468_REMOTE8 0x08 - -#define TMP468_SRST 0x20 -#define TMP468_THERM 0x21 -#define TMP468_THERM2 0x22 -#define TMP468_ROPEN 0x23 - -#define TMP468_CONFIGURATION 0x30 -#define TMP468_THERM_HYST 0x38 - -#define TMP468_LOCAL_LOW_LIMIT 0x39 -#define TMP468_LOCAL_HIGH_LIMT 0x3a - -#define TMP468_REMOTE1_OFFSET 0x40 -#define TMP468_REMOTE1_NFACTOR 0x41 -#define TMP468_REMOTE1_LOW_LIMIT 0x41 -#define TMP468_REMOTE1_HIGH_LIMIT 0x42 - -#define TMP468_REMOTE2_OFFSET 0x48 -#define TMP468_REMOTE2_NFACTOR 0x49 -#define TMP468_REMOTE2_LOW_LIMIT 0x4a -#define TMP468_REMOTE2_HIGH_LIMIT 0x4b - -#define TMP468_REMOTE3_OFFSET 0x50 -#define TMP468_REMOTE3_NFACTOR 0x51 -#define TMP468_REMOTE3_LOW_LIMIT 0x52 -#define TMP468_REMOTE3_HIGH_LIMIT 0x53 - -#define TMP468_REMOTE4_OFFSET 0x58 -#define TMP468_REMOTE4_NFACTOR 0x59 -#define TMP468_REMOTE4_LOW_LIMIT 0x59 -#define TMP468_REMOTE4_HIGH_LIMIT 0x5a - -#define TMP468_REMOTE5_OFFSET 0x60 -#define TMP468_REMOTE5_NFACTOR 0x61 -#define TMP468_REMOTE5_LOW_LIMIT 0x62 -#define TMP468_REMOTE5_HIGH_LIMIT 0x63 - -#define TMP468_REMOTE6_OFFSET 0x68 -#define TMP468_REMOTE6_NFACTOR 0x69 -#define TMP468_REMOTE6_LOW_LIMIT 0x6a -#define TMP468_REMOTE6_HIGH_LIMIT 0x6b - -#define TMP468_REMOTE7_OFFSET 0x70 -#define TMP468_REMOTE7_NFACTOR 0x71 -#define TMP468_REMOTE7_LOW_LIMIT 0x72 -#define TMP468_REMOTE7_HIGH_LIMIT 0x73 - -#define TMP468_REMOTE8_OFFSET 0x78 -#define TMP468_REMOTE8_NFACTOR 0x79 -#define TMP468_REMOTE8_LOW_LIMIT 0x7a -#define TMP468_REMOTE8_HIGH_LIMIT 0x7b - -#define TMP468_LOCK 0xc4 - -#define TMP468_DEVICE_ID 0xfd -#define TMP468_MANUFACTURER_ID 0xfe - -#define TMP468_SHUTDOWN BIT(5) - -enum tmp468_channel_id { - TMP468_CHANNEL_LOCAL, - - TMP468_CHANNEL_REMOTE1, - TMP468_CHANNEL_REMOTE2, - TMP468_CHANNEL_REMOTE3, - TMP468_CHANNEL_REMOTE4, - TMP468_CHANNEL_REMOTE5, - TMP468_CHANNEL_REMOTE6, - TMP468_CHANNEL_REMOTE7, - TMP468_CHANNEL_REMOTE8, - - TMP468_CHANNEL_COUNT -}; - -enum tmp468_power_state { - TMP468_POWER_OFF = 0, - TMP468_POWER_ON, - - TMP468_POWER_COUNT -}; - - -/** - * Get the last polled value of a sensor. - * - * @param idx Index to read. Idx indicates whether to read die - * temperature or external temperature. - * @param temp_ptr Destination for temperature in K. - * - * @return EC_SUCCESS if successful, non-zero if error. - */ -int tmp468_get_val(int idx, int *temp_ptr); - -/** - * Power control function of tmp432 temperature sensor. - * - * @param power_on TMP468_POWER_ON: turn tmp468 sensor on. - * TMP468_POWER_OFF: shut tmp468 sensor down. - * - * @return EC_SUCCESS if successful, non-zero if error. - */ -int tmp468_set_power(enum tmp468_power_state power_on); - -#endif /* __CROS_EC_TMP468_H */ diff --git a/driver/touchpad_elan.c b/driver/touchpad_elan.c deleted file mode 100644 index 4c7cb91a61..0000000000 --- a/driver/touchpad_elan.c +++ /dev/null @@ -1,765 +0,0 @@ -/* 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. - */ - -#include "common.h" -#include "console.h" -#include "gpio.h" -#include "hwtimer.h" -#include "hooks.h" -#include "i2c.h" -#include "sha256.h" -#include "shared_mem.h" -#include "task.h" -#include "tablet_mode.h" -#include "timer.h" -#include "touchpad.h" -#include "update_fw.h" -#include "util.h" -#include "usb_api.h" -#include "usb_hid_touchpad.h" -#include "watchdog.h" - -/* Console output macros */ -#define CPUTS(outstr) cputs(CC_TOUCHPAD, outstr) -#define CPRINTF(format, args...) cprintf(CC_TOUCHPAD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_TOUCHPAD, format, ## args) - -#define TASK_EVENT_POWER TASK_EVENT_CUSTOM_BIT(0) - -/******************************************************************************/ -/* How to talk to the controller */ -/******************************************************************************/ - -#define ELAN_VENDOR_ID 0x04f3 - -#define ETP_I2C_RESET 0x0100 -#define ETP_I2C_WAKE_UP 0x0800 -#define ETP_I2C_SLEEP 0x0801 - -#define ETP_I2C_STAND_CMD 0x0005 -#define ETP_I2C_UNIQUEID_CMD 0x0101 -#define ETP_I2C_FW_VERSION_CMD 0x0102 -#define ETP_I2C_OSM_VERSION_CMD 0x0103 -#define ETP_I2C_XY_TRACENUM_CMD 0x0105 -#define ETP_I2C_MAX_X_AXIS_CMD 0x0106 -#define ETP_I2C_MAX_Y_AXIS_CMD 0x0107 -#define ETP_I2C_RESOLUTION_CMD 0x0108 -#define ETP_I2C_PRESSURE_CMD 0x010A -#define ETP_I2C_SET_CMD 0x0300 -#define ETP_I2C_POWER_CMD 0x0307 -#define ETP_I2C_FW_CHECKSUM_CMD 0x030F - -#define ETP_ENABLE_ABS 0x0001 - -#define ETP_DISABLE_POWER 0x0001 - -#define ETP_I2C_REPORT_LEN 34 - -#define ETP_MAX_FINGERS 5 -#define ETP_FINGER_DATA_LEN 5 - -#define ETP_PRESSURE_OFFSET 25 -#define ETP_FWIDTH_REDUCE 90 - -#define ETP_REPORT_ID 0x5D -#define ETP_REPORT_ID_OFFSET 2 -#define ETP_TOUCH_INFO_OFFSET 3 -#define ETP_FINGER_DATA_OFFSET 4 -#define ETP_HOVER_INFO_OFFSET 30 -#define ETP_MAX_REPORT_LEN 34 - -#define ETP_IAP_START_ADDR 0x0083 - -#define ETP_I2C_IAP_RESET_CMD 0x0314 -#define ETP_I2C_IAP_RESET 0xF0F0 -#define ETP_I2C_IAP_CTRL_CMD 0x0310 -#define ETP_I2C_MAIN_MODE_ON BIT(9) -#define ETP_I2C_IAP_CMD 0x0311 -#define ETP_I2C_IAP_PASSWORD 0x1EA5 - -#define ETP_I2C_IAP_REG_L 0x01 -#define ETP_I2C_IAP_REG_H 0x06 - -#define ETP_FW_IAP_PAGE_ERR BIT(5) -#define ETP_FW_IAP_INTF_ERR BIT(4) - -#ifdef CONFIG_USB_UPDATE -/* The actual FW_SIZE depends on IC. */ -#define FW_SIZE CONFIG_TOUCHPAD_VIRTUAL_SIZE -#define FW_PAGE_SIZE 64 -#endif - -struct { - /* Max X/Y position */ - uint16_t max_x; - uint16_t max_y; - /* Scaling factor for finger width/height */ - uint16_t width_x; - uint16_t width_y; - /* Pressure adjustment */ - uint8_t pressure_adj; -} elan_tp_params; - -/* - * Report a more reasonable pressure value, so that no adjustment is necessary - * on Chrome OS side. 3216/1024 ~= 3.1416. - */ -const int pressure_mult = 3216; -const int pressure_div = 1024; - -static int elan_tp_read_cmd(uint16_t reg, uint16_t *val) -{ - uint8_t buf[2]; - - buf[0] = reg; - buf[1] = reg >> 8; - - return i2c_xfer(CONFIG_TOUCHPAD_I2C_PORT, - CONFIG_TOUCHPAD_I2C_ADDR_FLAGS, - buf, sizeof(buf), (uint8_t *)val, sizeof(*val)); -} - -static int elan_tp_write_cmd(uint16_t reg, uint16_t val) -{ - uint8_t buf[4]; - - buf[0] = reg; - buf[1] = reg >> 8; - buf[2] = val; - buf[3] = val >> 8; - - return i2c_xfer(CONFIG_TOUCHPAD_I2C_PORT, - CONFIG_TOUCHPAD_I2C_ADDR_FLAGS, - buf, sizeof(buf), NULL, 0); -} - -/* Power is on by default. */ -static int elan_tp_power = 1; - -static int elan_tp_set_power(int enable) -{ - int rv; - uint16_t val; - - if ((enable && elan_tp_power) || (!enable && !elan_tp_power)) - return EC_SUCCESS; - - CPRINTS("elan TP power %s", enable ? "on" : "off"); - - rv = elan_tp_read_cmd(ETP_I2C_POWER_CMD, &val); - if (rv) - goto out; - - if (enable) - val &= ~ETP_DISABLE_POWER; - else - val |= ETP_DISABLE_POWER; - - rv = elan_tp_write_cmd(ETP_I2C_POWER_CMD, val); - - elan_tp_power = enable; -out: - return rv; -} - -static int finger_status[ETP_MAX_FINGERS] = {0}; - -/* - * Timestamp of last interrupt (32 bits are enough as we divide the value by 100 - * and then put it in a 16-bit field). - */ -static uint32_t irq_ts; - -/* - * Read touchpad report. - * Returns 0 on success, positive (EC_RES_*) value on I2C error, and a negative - * value if the I2C transaction is successful but the data is invalid (fairly - * common). - */ -static int elan_tp_read_report(void) -{ - int rv; - uint8_t tp_buf[ETP_I2C_REPORT_LEN]; - int i, ri; - uint8_t touch_info; - uint8_t hover_info; - uint8_t *finger = tp_buf+ETP_FINGER_DATA_OFFSET; - struct usb_hid_touchpad_report report; - uint16_t timestamp; - - /* Compute and save timestamp early in case another interrupt comes. */ - timestamp = irq_ts / USB_HID_TOUCHPAD_TIMESTAMP_UNIT; - - rv = i2c_xfer(CONFIG_TOUCHPAD_I2C_PORT, - CONFIG_TOUCHPAD_I2C_ADDR_FLAGS, - NULL, 0, tp_buf, ETP_I2C_REPORT_LEN); - - if (rv) { - CPRINTS("read report error (%d)", rv); - return rv; - } - - if (tp_buf[ETP_REPORT_ID_OFFSET] != ETP_REPORT_ID) { - CPRINTS("Invalid report id (%x)", tp_buf[ETP_REPORT_ID_OFFSET]); - return -1; - } - - memset(&report, 0, sizeof(report)); - report.id = 0x01; - ri = 0; /* Next finger index in HID report */ - - touch_info = tp_buf[ETP_TOUCH_INFO_OFFSET]; - hover_info = tp_buf[ETP_HOVER_INFO_OFFSET]; - - for (i = 0; i < ETP_MAX_FINGERS; i++) { - int valid = touch_info & (1 << (3+i)); - - if (valid) { - int width = finger[3] & 0x0f; - int height = (finger[3] & 0xf0) >> 4; - int pressure = finger[4] + elan_tp_params.pressure_adj; - pressure = DIV_ROUND_NEAREST(pressure * pressure_mult, - pressure_div); - - width = MIN(4095, width * elan_tp_params.width_x); - height = MIN(4095, height * elan_tp_params.width_y); - pressure = MIN(1023, pressure); - - report.finger[ri].confidence = 1; - report.finger[ri].tip = 1; - report.finger[ri].inrange = 1; - report.finger[ri].id = i; - report.finger[ri].width = width; - report.finger[ri].height = height; - report.finger[ri].x = - ((finger[0] & 0xf0) << 4) | finger[1]; - report.finger[ri].y = - elan_tp_params.max_y - - (((finger[0] & 0x0f) << 8) | finger[2]); - report.finger[ri].pressure = pressure; - finger += ETP_FINGER_DATA_LEN; - ri++; - finger_status[i] = 1; - } else if (finger_status[i]) { - report.finger[ri].id = i; - /* When a finger is leaving, it's not a plam */ - report.finger[ri].confidence = 1; - ri++; - finger_status[i] = 0; - } - } - - report.count = ri; - report.timestamp = timestamp; - - if (touch_info & 0x01) { - /* Do not report zero-finger click events */ - if (report.count > 0) - report.button = 1; - } - - if (hover_info & 0x40) { - /* TODO(b/35582031): Report hover event */ - CPRINTF("[TP] hover!\n"); - } - - set_touchpad_report(&report); - - return 0; -} - -/* Initialize the controller ICs after reset */ -static void elan_tp_init(void) -{ - int rv; - uint8_t val[2]; - int dpi_x, dpi_y; - - CPRINTS("%s", __func__); - - elan_tp_write_cmd(ETP_I2C_STAND_CMD, ETP_I2C_RESET); - msleep(100); - rv = i2c_xfer(CONFIG_TOUCHPAD_I2C_PORT, - CONFIG_TOUCHPAD_I2C_ADDR_FLAGS, - NULL, 0, val, sizeof(val)); - - CPRINTS("reset rv %d buf=%04x", rv, *((uint16_t *)val)); - if (rv) - goto out; - - /* Read min/max */ - rv = elan_tp_read_cmd(ETP_I2C_MAX_X_AXIS_CMD, &elan_tp_params.max_x); - if (rv) - goto out; - rv = elan_tp_read_cmd(ETP_I2C_MAX_Y_AXIS_CMD, &elan_tp_params.max_y); - if (rv) - goto out; - - /* Read min/max */ - rv = elan_tp_read_cmd(ETP_I2C_XY_TRACENUM_CMD, (uint16_t *)val); - if (rv) - goto out; - if (val[0] == 0 || val[1] == 0) { - CPRINTS("Invalid XY_TRACENUM"); - goto out; - } - - /* ETP_FWIDTH_REDUCE reduces the apparent width to avoid treating large - * finger as palm. Multiply value by 2 as HID multitouch divides it. - */ - elan_tp_params.width_x = - 2 * ((elan_tp_params.max_x / val[0]) - ETP_FWIDTH_REDUCE); - elan_tp_params.width_y = - 2 * ((elan_tp_params.max_y / val[1]) - ETP_FWIDTH_REDUCE); - - rv = elan_tp_read_cmd(ETP_I2C_PRESSURE_CMD, (uint16_t *)val); - if (rv) - goto out; - elan_tp_params.pressure_adj = (val[0] & 0x10) ? 0 : ETP_PRESSURE_OFFSET; - - rv = elan_tp_read_cmd(ETP_I2C_RESOLUTION_CMD, (uint16_t *)val); - if (rv) - goto out; - - dpi_x = 10*val[0] + 790; - dpi_y = 10*val[1] + 790; - - CPRINTS("max=%d/%d width=%d/%d adj=%d dpi=%d/%d", - elan_tp_params.max_x, elan_tp_params.max_y, - elan_tp_params.width_x, elan_tp_params.width_y, - elan_tp_params.pressure_adj, dpi_x, dpi_y); - -#ifdef CONFIG_USB_HID_TOUCHPAD - /* - * Sanity check dimensions provided at build time. - * - dpi == logical dimension / physical dimension (inches) - * (254 tenths of mm per inch) - */ - if (elan_tp_params.max_x != CONFIG_USB_HID_TOUCHPAD_LOGICAL_MAX_X || - elan_tp_params.max_y != CONFIG_USB_HID_TOUCHPAD_LOGICAL_MAX_Y || - dpi_x != 254*CONFIG_USB_HID_TOUCHPAD_LOGICAL_MAX_X / - CONFIG_USB_HID_TOUCHPAD_PHYSICAL_MAX_X || - dpi_y != 254*CONFIG_USB_HID_TOUCHPAD_LOGICAL_MAX_Y / - CONFIG_USB_HID_TOUCHPAD_PHYSICAL_MAX_Y) { - CPRINTS("*** TP mismatch!"); - } -#endif - - /* Switch to absolute mode */ - rv = elan_tp_write_cmd(ETP_I2C_SET_CMD, ETP_ENABLE_ABS); - if (rv) - goto out; - - /* Sleep control off */ - rv = elan_tp_write_cmd(ETP_I2C_STAND_CMD, ETP_I2C_WAKE_UP); - - /* Enable interrupt to fetch reports */ - gpio_enable_interrupt(GPIO_TOUCHPAD_INT); - -out: - CPRINTS("%s:%d", __func__, rv); - - return; -} -DECLARE_DEFERRED(elan_tp_init); - -#ifdef CONFIG_USB_UPDATE -int touchpad_get_info(struct touchpad_info *tp) -{ - int rv; - uint16_t val; - - tp->status = EC_RES_SUCCESS; - tp->vendor = ELAN_VENDOR_ID; - - /* Get unique ID, FW, SM version. */ - rv = elan_tp_read_cmd(ETP_I2C_UNIQUEID_CMD, &val); - if (rv) - return -1; - tp->elan.id = val; - - rv = elan_tp_read_cmd(ETP_I2C_FW_VERSION_CMD, &val); - if (rv) - return -1; - tp->elan.fw_version = val & 0xff; - - rv = elan_tp_read_cmd(ETP_I2C_FW_CHECKSUM_CMD, &val); - if (rv) - return -1; - tp->elan.fw_checksum = val; - - return sizeof(*tp); -} - -static int elan_in_main_mode(void) -{ - uint16_t val; - - elan_tp_read_cmd(ETP_I2C_IAP_CTRL_CMD, &val); - return val & ETP_I2C_MAIN_MODE_ON; -} - -static int elan_get_ic_page_count(void) -{ - uint16_t ic_type; - - elan_tp_read_cmd(ETP_I2C_OSM_VERSION_CMD, &ic_type); - CPRINTS("%s: ic_type:%04X.", __func__, ic_type); - switch (ic_type >> 8) { - case 0x09: - return 768; - case 0x0D: - return 896; - case 0x00: - case 0x10: - return 1024; - } - return -1; -} - -static int elan_prepare_for_update(void) -{ - uint16_t rx_buf; - int initial_mode; - - initial_mode = elan_in_main_mode(); - if (!initial_mode) { - CPRINTS("%s: In IAP mode, reset IC.", __func__); - elan_tp_write_cmd(ETP_I2C_IAP_RESET_CMD, ETP_I2C_IAP_RESET); - msleep(30); - } - /* Send the passphrase */ - elan_tp_write_cmd(ETP_I2C_IAP_CMD, ETP_I2C_IAP_PASSWORD); - msleep(initial_mode ? 100 : 30); - - /* We should be in the IAP mode now */ - if (elan_in_main_mode()) { - CPRINTS("%s: Failure to enter IAP mode.", __func__); - return EC_ERROR_UNKNOWN; - } - - /* Send the passphrase again */ - elan_tp_write_cmd(ETP_I2C_IAP_CMD, ETP_I2C_IAP_PASSWORD); - msleep(30); - - /* Verify the password */ - if (elan_tp_read_cmd(ETP_I2C_IAP_CMD, &rx_buf)) { - CPRINTS("%s: Cannot read IAP password.", __func__); - return EC_ERROR_UNKNOWN; - } - if (rx_buf != ETP_I2C_IAP_PASSWORD) { - CPRINTS("%s: Got an unexpected IAP password %0x4x.", __func__, - rx_buf); - return EC_ERROR_UNKNOWN; - } - return EC_SUCCESS; -} - -static int touchpad_update_page(const uint8_t *data) -{ - uint8_t page_store[FW_PAGE_SIZE + 4]; - uint16_t checksum = 0; - uint16_t rx_buf; - int i, rv; - - for (i = 0; i < FW_PAGE_SIZE; i += 2) - checksum += ((uint16_t)(data[i + 1]) << 8) | (data[i]); - - page_store[0] = ETP_I2C_IAP_REG_L; - page_store[1] = ETP_I2C_IAP_REG_H; - memcpy(page_store + 2, data, FW_PAGE_SIZE); - page_store[FW_PAGE_SIZE + 2 + 0] = checksum & 0xff; - page_store[FW_PAGE_SIZE + 2 + 1] = (checksum >> 8) & 0xff; - - rv = i2c_xfer(CONFIG_TOUCHPAD_I2C_PORT, - CONFIG_TOUCHPAD_I2C_ADDR_FLAGS, - page_store, sizeof(page_store), NULL, 0); - if (rv) - return rv; - msleep(20); - - rv = elan_tp_read_cmd(ETP_I2C_IAP_CTRL_CMD, &rx_buf); - - if (rv || (rx_buf & (ETP_FW_IAP_PAGE_ERR | ETP_FW_IAP_INTF_ERR))) { - CPRINTS("%s: IAP reports failed write : %x.", - __func__, rx_buf); - return EC_ERROR_UNKNOWN; - } - return 0; -} - -int touchpad_update_write(int offset, int size, const uint8_t *data) -{ - static int iap_addr = -1; - int addr, rv, page_count; - - CPRINTS("%s %08x %d", __func__, offset, size); - - if (offset == 0) { - /* Verify the IC type is aligned with defined firmware size */ - page_count = elan_get_ic_page_count(); - if (FW_PAGE_SIZE * page_count != FW_SIZE) { - CPRINTS("%s: IC(%d*%d) size and FW_SIZE(%d) mismatch", - __func__, page_count, FW_PAGE_SIZE, FW_SIZE); - return EC_ERROR_UNKNOWN; - } - - gpio_disable_interrupt(GPIO_TOUCHPAD_INT); - CPRINTS("%s: prepare fw update.", __func__); - rv = elan_prepare_for_update(); - if (rv) - return rv; - iap_addr = 0; - } - - if (offset <= (ETP_IAP_START_ADDR * 2) && - (ETP_IAP_START_ADDR * 2) < (offset + size)) { - iap_addr = ((data[ETP_IAP_START_ADDR * 2 - offset + 1] << 8) | - data[ETP_IAP_START_ADDR * 2 - offset]) << 1; - CPRINTS("%s: payload starts from 0x%x.", __func__, iap_addr); - } - - /* Data that comes in must align with FW_PAGE_SIZE */ - if (offset % FW_PAGE_SIZE) - return EC_ERROR_INVAL; - - for (addr = (offset / FW_PAGE_SIZE) * FW_PAGE_SIZE; - addr < (offset + size); addr += FW_PAGE_SIZE) { - if (iap_addr > addr) /* Skip chunk */ - continue; - rv = touchpad_update_page(data + addr - offset); - if (rv) - return rv; - CPRINTF("/p%d", addr / FW_PAGE_SIZE); - watchdog_reload(); - } - CPRINTF("\n"); - - if (offset + size == FW_SIZE) { - CPRINTS("%s: End update, wait for reset.", __func__); - hook_call_deferred(&elan_tp_init_data, 600 * MSEC); - } - return EC_SUCCESS; -} - -/* Debugging mode. */ - -/* Allowed debug commands. We only store a hash of the allowed commands. */ -#define TOUCHPAD_ELAN_DEBUG_CMD_LENGTH 50 -#define TOUCHPAD_ELAN_DEBUG_NUM_CMD 2 - -static const uint8_t -allowed_command_hashes[TOUCHPAD_ELAN_DEBUG_NUM_CMD][SHA256_DIGEST_SIZE] = { - { - 0x0a, 0xf6, 0x37, 0x03, 0x93, 0xb2, 0xde, 0x8c, - 0x56, 0x7b, 0x86, 0xba, 0xa6, 0x79, 0xe3, 0xa3, - 0x8b, 0xc7, 0x15, 0xf2, 0x53, 0xcf, 0x71, 0x8b, - 0x3d, 0xe4, 0x81, 0xf9, 0xd9, 0xa8, 0x78, 0x48 - }, - { - 0xac, 0xe5, 0xbf, 0x17, 0x1f, 0xde, 0xce, 0x76, - 0x0c, 0x0e, 0xf8, 0xa2, 0xe9, 0x67, 0x2d, 0xc9, - 0x1b, 0xd4, 0xba, 0x34, 0x51, 0xca, 0xf6, 0x6d, - 0x7b, 0xb2, 0x1f, 0x14, 0x82, 0x1c, 0x0b, 0x74 - }, -}; - -/* Debugging commands need to allocate a <=1k buffer. */ -SHARED_MEM_CHECK_SIZE(1024); - -int touchpad_debug(const uint8_t *param, unsigned int param_size, - uint8_t **data, unsigned int *data_size) -{ - static uint8_t *buffer; - static unsigned int buffer_size; - unsigned int offset; - - /* Offset parameter is 1 byte. */ - if (param_size < 1) - return EC_RES_INVALID_PARAM; - - /* - * Debug command, compute SHA-256, check that it matches allowed hashes, - * and execute I2C command. - * - * param[0] must be 0xff - * param[1] is the offset of the command in the data - * param[2] is the command length - * param[3-4] is the read-back length (MSB first), can be 0 - * param[5-49] is verified using SHA-256 hash. - */ - if (param[0] == 0xff && param_size == TOUCHPAD_ELAN_DEBUG_CMD_LENGTH) { - struct sha256_ctx ctx; - uint8_t *command_hash; - unsigned int offset = param[1]; - unsigned int write_length = param[2]; - unsigned int read_length = - ((unsigned int)param[3] << 8) | param[4]; - int i; - int match; - int rv; - - if (offset < 5 || write_length == 0 || - (offset + write_length) >= TOUCHPAD_ELAN_DEBUG_CMD_LENGTH) - return EC_RES_INVALID_PARAM; - - SHA256_init(&ctx); - SHA256_update(&ctx, param+5, TOUCHPAD_ELAN_DEBUG_CMD_LENGTH-5); - command_hash = SHA256_final(&ctx); - - match = 0; - for (i = 0; i < TOUCHPAD_ELAN_DEBUG_NUM_CMD; i++) { - if (!memcmp(command_hash, allowed_command_hashes[i], - sizeof(allowed_command_hashes[i]))) { - match = 1; - break; - } - } - - if (!match) - return EC_RES_INVALID_PARAM; - - if (buffer) { - shared_mem_release(buffer); - buffer = NULL; - } - - buffer_size = read_length; - - if (read_length > 0) { - if (shared_mem_acquire(buffer_size, - (char **)&buffer) != EC_SUCCESS) { - buffer = NULL; - buffer_size = 0; - return EC_RES_BUSY; - } - - memset(buffer, 0, buffer_size); - } - - rv = i2c_xfer(CONFIG_TOUCHPAD_I2C_PORT, - CONFIG_TOUCHPAD_I2C_ADDR_FLAGS, - ¶m[offset], write_length, - buffer, read_length); - - if (rv) - return EC_RES_BUS_ERROR; - - return EC_RES_SUCCESS; - } - - /* - * Data request: Retrieve previously read data from buffer, in blocks of - * 64 bytes. - */ - offset = param[0] * 64; - - if (!buffer) - return EC_RES_UNAVAILABLE; - - if (offset >= buffer_size) { - shared_mem_release(buffer); - buffer = NULL; - *data = NULL; - *data_size = 0; - return EC_RES_OVERFLOW; - } - - *data = buffer + offset; - *data_size = MIN(64, buffer_size - offset); - - return EC_RES_SUCCESS; -} -#endif - -/* - * Try to read touchpad report up to 3 times, reset the touchpad if we still - * fail. - */ -void elan_tp_read_report_retry(void) -{ - int ret; - int retry = 3; - - while (retry--) { - ret = elan_tp_read_report(); - - if (ret <= 0) - return; - - /* Try again */ - msleep(1); - } - - /* Failed to read data, reset the touchpad. */ - CPRINTF("Resetting TP.\n"); - board_touchpad_reset(); - elan_tp_init(); -} - -void touchpad_interrupt(enum gpio_signal signal) -{ - irq_ts = __hw_clock_source_read(); - - task_wake(TASK_ID_TOUCHPAD); -} - -/* Make a decision on touchpad power, based on USB and tablet mode status. */ -static void touchpad_power_control(void) -{ - static int enabled = 1; - int enable = 1; - -#ifdef CONFIG_USB_SUSPEND - enable = enable && - (!usb_is_suspended() || usb_is_remote_wakeup_enabled()); -#endif - -#ifdef CONFIG_TABLET_MODE - enable = enable && !tablet_get_mode(); -#endif - - if (enabled == enable) - return; - - elan_tp_set_power(enable); - - enabled = enable; -} - -void touchpad_task(void *u) -{ - uint32_t event; - - elan_tp_init(); - touchpad_power_control(); - - while (1) { - event = task_wait_event(-1); - - if (event & TASK_EVENT_WAKE) - elan_tp_read_report_retry(); - - if (event & TASK_EVENT_POWER) - touchpad_power_control(); - } -} - -/* - * When USB PM status changes, or tablet mode changes, call in the main task to - * decide whether to turn touchpad on or off. - */ -#if defined(CONFIG_USB_SUSPEND) || defined(CONFIG_TABLET_MODE) -static void touchpad_power_change(void) -{ - task_set_event(TASK_ID_TOUCHPAD, TASK_EVENT_POWER, 0); -} -#endif -#ifdef CONFIG_USB_SUSPEND -DECLARE_HOOK(HOOK_USB_PM_CHANGE, touchpad_power_change, HOOK_PRIO_DEFAULT); -#endif -#ifdef CONFIG_TABLET_MODE -DECLARE_HOOK(HOOK_TABLET_MODE_CHANGE, touchpad_power_change, HOOK_PRIO_DEFAULT); -#endif diff --git a/driver/touchpad_gt7288.c b/driver/touchpad_gt7288.c deleted file mode 100644 index ccc98622d5..0000000000 --- a/driver/touchpad_gt7288.c +++ /dev/null @@ -1,227 +0,0 @@ -/* Copyright 2019 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. - */ - -#include <stdbool.h> - -#include "common.h" -#include "console.h" -#include "hooks.h" -#include "i2c.h" -#include "task.h" -#include "touchpad_gt7288.h" -#include "util.h" - -/* Define this to enable various warning messages during report parsing. */ -#undef DEBUG_CHECKS - -#define CPRINTS(format, args...) cprints(CC_TOUCHPAD, format, ## args) - -#define GT7288_SLAVE_ADDRESS 0x14 - -#define GT7288_REPORT_ID_PTP 0x04 - -#define GT7288_BUTTON_STATE_UP 0x80 -#define GT7288_BUTTON_STATE_DOWN 0x81 - -#define GT7288_REG_HID_DESCRIPTOR 0x0001 -#define GT7288_REG_REPORT_DESCRIPTOR 0x0002 - -#define GT7288_HID_DESCRIPTOR_LENGTH 0x1E -#define GT7288_REPORT_DESCRIPTOR_LENGTH 0x1AE -#define GT7288_REPORT_LENGTH 16 - -/** - * Reads a descriptor using the Conventional Read Mode. - * - * @param[in] register_id The register containing the descriptor to read. - * @param[out] data The data that is read. - * @param[in] max_length The maximum length of data. - * - * @return EC_SUCCESS or an error code. - */ -static int gt7288_read_desc(uint16_t register_id, uint8_t *data, - size_t max_length) -{ - uint8_t reg_bytes[] = { - register_id & 0xFF, (register_id & 0xFF00) >> 8 - }; - return i2c_xfer(CONFIG_TOUCHPAD_I2C_PORT, GT7288_SLAVE_ADDRESS, - reg_bytes, sizeof(reg_bytes), data, max_length); -} - -int gt7288_get_version_info(struct gt7288_version_info *info) -{ - uint8_t data[GT7288_HID_DESCRIPTOR_LENGTH]; - - RETURN_ERROR(gt7288_read_desc(GT7288_REG_HID_DESCRIPTOR, data, - sizeof(data))); - info->product_id = UINT16_FROM_BYTE_ARRAY_LE(data, 22); - info->version_id = UINT16_FROM_BYTE_ARRAY_LE(data, 24); - return EC_SUCCESS; -} - -static void gt7288_translate_contact(const uint8_t *data, - struct gt7288_contact *contact) -{ - if (IS_ENABLED(DEBUG_CHECKS)) { - uint8_t report_id = data[2]; - - if (report_id != GT7288_REPORT_ID_PTP) { - CPRINTS("WARNING: unexpected report ID 0x%02X (expected 0x%02X).", - report_id, GT7288_REPORT_ID_PTP); - } - } - - contact->id = data[3] >> 4; - /* Note: these bits appear to be in the wrong order in the programming - * guide, verified by experimentation. - */ - contact->tip = (data[3] & BIT(1)) >> 1; - contact->confidence = data[3] & BIT(0); - contact->x = UINT16_FROM_BYTE_ARRAY_LE(data, 4); - contact->y = UINT16_FROM_BYTE_ARRAY_LE(data, 6); - contact->width = data[12]; - contact->height = data[13]; -} - -static int gt7288_read(uint8_t *data, size_t max_length) -{ - return i2c_xfer(CONFIG_TOUCHPAD_I2C_PORT, GT7288_SLAVE_ADDRESS, - NULL, 0, data, max_length); -} - -int gt7288_read_ptp_report(struct gt7288_ptp_report *report) -{ - size_t i; - uint8_t data[GT7288_REPORT_LENGTH]; - - RETURN_ERROR(gt7288_read(data, sizeof(data))); - report->timestamp = UINT16_FROM_BYTE_ARRAY_LE(data, 8); - - if (data[10] > GT7288_MAX_CONTACTS) { - if (IS_ENABLED(DEBUG_CHECKS)) - CPRINTS("ERROR: too many contacts (%d > %d).", - data[10], GT7288_MAX_CONTACTS); - return EC_ERROR_HW_INTERNAL; - } - report->num_contacts = data[10]; - - if (IS_ENABLED(DEBUG_CHECKS) && data[11] != GT7288_BUTTON_STATE_UP && - data[11] != GT7288_BUTTON_STATE_DOWN) { - CPRINTS("WARNING: unexpected button state 0x%02X (expected 0x%02X or 0x%02X).", - data[11], GT7288_BUTTON_STATE_UP, - GT7288_BUTTON_STATE_DOWN); - } - report->button_down = data[11] == GT7288_BUTTON_STATE_DOWN; - - gt7288_translate_contact(data, &report->contacts[0]); - - for (i = 1; i < report->num_contacts; i++) { - RETURN_ERROR(gt7288_read(data, sizeof(data))); - gt7288_translate_contact(data, &report->contacts[i]); - } - return EC_SUCCESS; -} - -#ifdef CONFIG_CMD_GT7288 -static int command_gt7288_read_desc(int argc, char **argv) -{ - uint16_t register_id; - long parsed_arg; - char *end; - int i; - uint8_t data[GT7288_HID_DESCRIPTOR_LENGTH]; - - if (argc != 2) - return EC_ERROR_PARAM_COUNT; - - parsed_arg = strtoi(argv[1], &end, 0); - if (parsed_arg < 0 || parsed_arg > UINT16_MAX || end == argv[1]) - return EC_ERROR_PARAM1; - register_id = parsed_arg; - - RETURN_ERROR(gt7288_read_desc(register_id, data, sizeof(data))); - - ccprintf("Data: "); - for (i = 0; i < sizeof(data); i++) - ccprintf("%02X ", data[i]); - ccprintf("\n"); - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(gt7288_desc, command_gt7288_read_desc, - "register", - "Read a descriptor on the GT7288"); - -static int command_gt7288_read_report_descriptor(int argc, char **argv) -{ - int i; - uint8_t data[64]; - size_t bytes_read = 0; - - if (argc != 1) - return EC_ERROR_PARAM_COUNT; - - /* The report descriptor is bigger than the Maxim I2C code can handle in - * one go, so we have to split it into chunks. - */ - RETURN_ERROR(gt7288_read_desc(GT7288_REG_REPORT_DESCRIPTOR, NULL, 0)); - ccprintf("Report descriptor: "); - while (bytes_read < GT7288_REPORT_DESCRIPTOR_LENGTH) { - size_t bytes_to_read = - MIN(GT7288_REPORT_DESCRIPTOR_LENGTH - bytes_read, - sizeof(data)); - RETURN_ERROR(gt7288_read(data, bytes_to_read)); - - for (i = 0; i < sizeof(data); i++) - ccprintf("%02X ", data[i]); - - bytes_read += bytes_to_read; - } - ccprintf("\n"); - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(gt7288_repdesc, command_gt7288_read_report_descriptor, - "", "Read the report descriptor on the GT7288"); - -static int command_gt7288_ver(int argc, char **argv) -{ - struct gt7288_version_info info; - - if (argc != 1) - return EC_ERROR_PARAM_COUNT; - - RETURN_ERROR(gt7288_get_version_info(&info)); - ccprintf("Product ID: 0x%04X\n", info.product_id); - ccprintf("Version ID: 0x%04X\n", info.version_id); - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(gt7288_ver, command_gt7288_ver, "", - "Read version information from the GT7288"); - -static int command_gt7288_report(int argc, char **argv) -{ - int i; - struct gt7288_ptp_report report; - - RETURN_ERROR(gt7288_read_ptp_report(&report)); - ccprintf("Timestamp %d, button %s, %d contacts\n", report.timestamp, - report.button_down ? "down" : "up", report.num_contacts); - if (report.num_contacts == 0) - return EC_SUCCESS; - - ccprintf("ID, X, Y, width, height, tip, confidence\n"); - for (i = 0; i < report.num_contacts; i++) { - struct gt7288_contact *contact = &report.contacts[i]; - - ccprintf("%2d, %4d, %4d, %5d, %6d, %3d, %10d\n", contact->id, - contact->x, contact->y, contact->width, - contact->height, contact->tip, contact->confidence); - } - - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(gt7288_rep, command_gt7288_report, "", - "Read a report from the GT7288."); -#endif /* CONFIG_CMD_GT7288 */ diff --git a/driver/touchpad_gt7288.h b/driver/touchpad_gt7288.h deleted file mode 100644 index c89c586784..0000000000 --- a/driver/touchpad_gt7288.h +++ /dev/null @@ -1,84 +0,0 @@ -/* Copyright 2019 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. - */ - -/* Driver for the Goodix GT7288 touch controller. */ - -#ifndef __CROS_EC_TOUCHPAD_GT7288_H -#define __CROS_EC_TOUCHPAD_GT7288_H - -#include <stdbool.h> -#include <stddef.h> - -/* The maximum number of contacts that can be reported at once. */ -#define GT7288_MAX_CONTACTS 5 - -/** - * Version information for the chip. - */ -struct gt7288_version_info { - /** HID product ID (0x01F0 for touchpads, 0x01F1 for touchscreens). */ - uint16_t product_id; - /** - * The firmware version. For touchpads equipped with a fingerprint - * sensor, the MSB will be 1. - */ - uint16_t version_id; -}; - -/** - * Reads version information from the GT7288. - * - * @param[out] info The version information. - * - * @return EC_SUCCESS or an error code. - */ -int gt7288_get_version_info(struct gt7288_version_info *info); - -/** - * Data describing a single contact. - */ -struct gt7288_contact { - /** - * A 4-bit ID that uniquely identifies the contact during its lifecycle. - */ - uint8_t id; - /** The absolute X coordinate. */ - uint16_t x; - /** The absolute Y coordinate. */ - uint16_t y; - /** The width of the contact (with firmware version 4 or greater). */ - uint8_t width; - /** The height of the contact (with firmware version 4 or greater). */ - uint8_t height; - /** Whether the finger is touching the pad. (Currently always true.) */ - bool tip; - /** Whether the touch is a finger (true) or palm (false). */ - bool confidence; -}; - -/** - * Data from a complete report in PTP mode. - */ -struct gt7288_ptp_report { - /** A relative timestamp, in units of 100µs. */ - uint16_t timestamp; - /** The number of contacts on the pad. */ - size_t num_contacts; - /** Whether the button is pressed. */ - bool button_down; - /** An array of structs describing the individual contacts. */ - struct gt7288_contact contacts[GT7288_MAX_CONTACTS]; -}; - -/** - * Reads a complete report, when the GT7288 is in PTP mode. - * - * @param[out] report The report that is read. - * - * @return EC_SUCCESS or an error code. - */ -int gt7288_read_ptp_report(struct gt7288_ptp_report *report); - -#endif /* __CROS_EC_TOUCHPAD_GT7288_H */ diff --git a/driver/touchpad_st.c b/driver/touchpad_st.c deleted file mode 100644 index a49ab2d7e2..0000000000 --- a/driver/touchpad_st.c +++ /dev/null @@ -1,1895 +0,0 @@ -/* Copyright 2018 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. - */ - -#include "atomic.h" -#include "board.h" -#include "common.h" -#include "console.h" -#include "gpio.h" -#include "hwtimer.h" -#include "hooks.h" -#include "i2c.h" -#include "registers.h" -#include "spi.h" -#include "task.h" -#include "tablet_mode.h" -#include "timer.h" -#include "touchpad.h" -#include "touchpad_st.h" -#include "update_fw.h" -#include "usb_api.h" -#include "usb_hid_touchpad.h" -#include "usb_isochronous.h" -#include "util.h" -#include "watchdog.h" - -/* Console output macros */ -#define CC_TOUCHPAD CC_USB -#define CPUTS(outstr) cputs(CC_TOUCHPAD, outstr) -#define CPRINTF(format, args...) cprintf(CC_TOUCHPAD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_TOUCHPAD, format, ## args) - -#define TASK_EVENT_POWER TASK_EVENT_CUSTOM_BIT(0) -#define TASK_EVENT_TP_UPDATED TASK_EVENT_CUSTOM_BIT(1) - -#define SPI (&(spi_devices[SPI_ST_TP_DEVICE_ID])) - -BUILD_ASSERT(sizeof(struct st_tp_event_t) == 8); -BUILD_ASSERT(BYTES_PER_PIXEL == 1); - -/* Function prototypes */ -static int st_tp_panel_init(int full); -static int st_tp_read_all_events(int show_error); -static int st_tp_read_host_buffer_header(void); -static int st_tp_send_ack(void); -static int st_tp_start_scan(void); -static int st_tp_stop_scan(void); -static int st_tp_update_system_state(int new_state, int mask); -static void touchpad_power_control(void); - -/* Global variables */ -/* - * Current system state, meaning of each bit is defined below. - */ -static int system_state; - -#define SYSTEM_STATE_DEBUG_MODE BIT(0) -#define SYSTEM_STATE_ENABLE_HEAT_MAP BIT(1) -#define SYSTEM_STATE_ENABLE_DOME_SWITCH BIT(2) -#define SYSTEM_STATE_ACTIVE_MODE BIT(3) -#define SYSTEM_STATE_DOME_SWITCH_LEVEL BIT(4) -#define SYSTEM_STATE_READY BIT(5) - -/* - * Pending action for touchpad. - */ -static int tp_control; - -#define TP_CONTROL_SHALL_HALT BIT(0) -#define TP_CONTROL_SHALL_RESET BIT(1) -#define TP_CONTROL_SHALL_INIT BIT(2) -#define TP_CONTROL_SHALL_INIT_FULL BIT(3) -#define TP_CONTROL_SHALL_DUMP_ERROR BIT(4) -#define TP_CONTROL_RESETTING BIT(5) -#define TP_CONTROL_INIT BIT(6) -#define TP_CONTROL_INIT_FULL BIT(7) - -/* - * Number of times we have reset the touchpad because of errors. - */ -static int tp_reset_retry_count; - -#define MAX_TP_RESET_RETRY_COUNT 3 - -static int dump_memory_on_error; - -/* - * Bitmap to track if a finger exists. - */ -static int touch_slot; - -/* - * Timestamp of last interrupt (32 bits are enough as we divide the value by 100 - * and then put it in a 16-bit field). - */ -static uint32_t irq_ts; - -/* - * Cached system info. - */ -static struct st_tp_system_info_t system_info; - -static struct { -#if ST_TP_DUMMY_BYTE == 1 - uint8_t dummy; -#endif - union { - uint8_t bytes[512]; - struct st_tp_host_buffer_header_t buffer_header; - struct st_tp_host_buffer_heat_map_t heat_map; - struct st_tp_host_data_header_t data_header; - struct st_tp_event_t events[32]; - uint32_t dump_info[32]; - } /* anonymous */; -} __packed rx_buf; - - -#ifdef CONFIG_USB_ISOCHRONOUS -#define USB_ISO_PACKET_SIZE 256 -/* - * Header of each USB pacaket. - */ -struct packet_header_t { - uint8_t index; - -#define HEADER_FLAGS_NEW_FRAME BIT(0) - uint8_t flags; -} __packed; -BUILD_ASSERT(sizeof(struct packet_header_t) < USB_ISO_PACKET_SIZE); - -static struct packet_header_t packet_header; - -/* What will be sent to USB interface. */ -struct st_tp_usb_packet_t { -#define USB_FRAME_FLAGS_BUTTON BIT(0) - /* - * This will be true if user clicked on touchpad. - * TODO(b/70482333): add corresponding code for button signal. - */ - uint8_t flags; - - /* - * This will be `st_tp_host_buffer_heat_map_t.frame` but each pixel - * will be scaled to 8 bits value. - */ - uint8_t frame[ST_TOUCH_ROWS * ST_TOUCH_COLS]; -} __packed; - -/* Next buffer index SPI will write to. */ -static volatile uint32_t spi_buffer_index; -/* Next buffer index USB will read from. */ -static volatile uint32_t usb_buffer_index; -static struct st_tp_usb_packet_t usb_packet[2]; /* double buffering */ -/* How many bytes we have transmitted. */ -static size_t transmit_report_offset; - -/* Function prototypes */ -static int get_heat_map_addr(void); -static void print_frame(void); -static void st_tp_disable_heat_map(void); -static void st_tp_enable_heat_map(void); -static int st_tp_read_frame(void); -static void st_tp_interrupt_send(void); -DECLARE_DEFERRED(st_tp_interrupt_send); -#endif - - -/* Function implementations */ - -static void set_bits(int *lvalue, int rvalue, int mask) -{ - *lvalue &= ~mask; - *lvalue |= rvalue & mask; -} - -/* - * Parse a finger report from ST event and save it to (report)->finger. - * - * @param report: pointer to a USB HID touchpad report. - * @param event: a pointer event from ST. - * @param i: array index for next finger. - * - * @return array index of next finger (i.e. (i + 1) if a finger is added). - */ -static int st_tp_parse_finger(struct usb_hid_touchpad_report *report, - struct st_tp_event_t *event, - int i) -{ - const int id = event->finger.touch_id; - - /* This is not a finger */ - if (event->finger.touch_type == ST_TP_TOUCH_TYPE_INVALID) - return i; - - if (event->evt_id == ST_TP_EVENT_ID_ENTER_POINTER) - touch_slot |= 1 << id; - else if (event->evt_id == ST_TP_EVENT_ID_LEAVE_POINTER) - touch_slot &= ~BIT(id); - - /* We cannot report more fingers */ - if (i >= ARRAY_SIZE(report->finger)) { - CPRINTS("WARN: ST reports more than %d fingers", i); - return i; - } - - switch (event->evt_id) { - case ST_TP_EVENT_ID_ENTER_POINTER: - case ST_TP_EVENT_ID_MOTION_POINTER: - /* Pressure == 255 is a palm. */ - report->finger[i].confidence = (event->finger.z < 255); - report->finger[i].tip = 1; - report->finger[i].inrange = 1; - report->finger[i].id = id; - report->finger[i].pressure = event->finger.z; - report->finger[i].width = (event->finger.minor | - (event->minor_high << 4)) << 5; - report->finger[i].height = (event->finger.major | - (event->major_high << 4)) << 5; - - report->finger[i].x = (CONFIG_USB_HID_TOUCHPAD_LOGICAL_MAX_X - - event->finger.x); - report->finger[i].y = (CONFIG_USB_HID_TOUCHPAD_LOGICAL_MAX_Y - - event->finger.y); - break; - case ST_TP_EVENT_ID_LEAVE_POINTER: - report->finger[i].id = id; - /* When a finger is leaving, it's not a palm */ - report->finger[i].confidence = 1; - break; - } - return i + 1; -} - -/* - * Read domeswitch level from touchpad, and save in `system_state`. - * - * After calling this function, use - * `system_state & SYSTEM_STATE_DOME_SWITCH_LEVEL` - * to get current value. - * - * @return error code on failure. - */ -static int st_tp_check_domeswitch_state(void) -{ - int ret = st_tp_read_host_buffer_header(); - - if (ret) - return ret; - - ret = rx_buf.buffer_header.flags & ST_TP_BUFFER_HEADER_DOMESWITCH_LVL; - /* - * Domeswitch level from device is inverted. - * That is, 0 => pressed, 1 => released. - */ - set_bits(&system_state, - ret ? 0 : SYSTEM_STATE_DOME_SWITCH_LEVEL, - SYSTEM_STATE_DOME_SWITCH_LEVEL); - return 0; -} - -static int st_tp_write_hid_report(void) -{ - int ret, i, num_finger, num_events; - const int old_system_state = system_state; - int domeswitch_changed; - struct usb_hid_touchpad_report report; - - ret = st_tp_check_domeswitch_state(); - if (ret) - return ret; - - domeswitch_changed = ((old_system_state ^ system_state) & - SYSTEM_STATE_DOME_SWITCH_LEVEL); - - num_events = st_tp_read_all_events(1); - if (tp_control) - return 1; - - memset(&report, 0, sizeof(report)); - report.id = REPORT_ID_TOUCHPAD; - num_finger = 0; - - for (i = 0; i < num_events; i++) { - struct st_tp_event_t *e = &rx_buf.events[i]; - - switch (e->evt_id) { - case ST_TP_EVENT_ID_ENTER_POINTER: - case ST_TP_EVENT_ID_MOTION_POINTER: - case ST_TP_EVENT_ID_LEAVE_POINTER: - num_finger = st_tp_parse_finger(&report, e, num_finger); - break; - default: - break; - } - } - - if (!num_finger && !domeswitch_changed) /* nothing changed */ - return 0; - - /* Don't report 0 finger click. */ - if (num_finger && (system_state & SYSTEM_STATE_DOME_SWITCH_LEVEL)) - report.button = 1; - report.count = num_finger; - report.timestamp = irq_ts / USB_HID_TOUCHPAD_TIMESTAMP_UNIT; - - set_touchpad_report(&report); - return 0; -} - -static int st_tp_read_report(void) -{ - if (system_state & SYSTEM_STATE_ENABLE_HEAT_MAP) { -#ifdef CONFIG_USB_ISOCHRONOUS - /* - * Because we are using double buffering, so, if - * usb_buffer_index = N - * - * 1. spi_buffer_index == N => ok, both slots are empty - * 2. spi_buffer_index == N + 1 => ok, second slot is empty - * 3. spi_buffer_index == N + 2 => not ok, need to wait for USB - */ - if (spi_buffer_index - usb_buffer_index <= 1) { - if (st_tp_read_frame() == EC_SUCCESS) { - spi_buffer_index++; - if (system_state & SYSTEM_STATE_DEBUG_MODE) { - print_frame(); - usb_buffer_index++; - } - } - } - if (spi_buffer_index > usb_buffer_index) - hook_call_deferred(&st_tp_interrupt_send_data, 0); -#endif - } else { - st_tp_write_hid_report(); - } - return st_tp_send_ack(); -} - -static int st_tp_read_host_buffer_header(void) -{ - const uint8_t tx_buf[] = { ST_TP_CMD_READ_SPI_HOST_BUFFER, 0x00, 0x00 }; - int rx_len = ST_TP_DUMMY_BYTE + sizeof(rx_buf.buffer_header); - - return spi_transaction(SPI, tx_buf, sizeof(tx_buf), - (uint8_t *)&rx_buf, rx_len); -} - -static int st_tp_send_ack(void) -{ - uint8_t tx_buf[] = { ST_TP_CMD_SPI_HOST_BUFFER_ACK }; - - return spi_transaction(SPI, tx_buf, sizeof(tx_buf), NULL, 0); -} - -static int st_tp_update_system_state(int new_state, int mask) -{ - int ret = EC_SUCCESS; - int need_locked_scan_mode = 0; - - /* copy reserved bits */ - set_bits(&new_state, system_state, ~mask); - - mask = SYSTEM_STATE_DEBUG_MODE; - if ((new_state & mask) != (system_state & mask)) - set_bits(&system_state, new_state, mask); - - mask = SYSTEM_STATE_ENABLE_HEAT_MAP | SYSTEM_STATE_ENABLE_DOME_SWITCH; - if ((new_state & mask) != (system_state & mask)) { - uint8_t tx_buf[] = { - ST_TP_CMD_WRITE_FEATURE_SELECT, - 0x05, - 0 - }; - if (new_state & SYSTEM_STATE_ENABLE_HEAT_MAP) { - CPRINTS("Heatmap enabled"); - tx_buf[2] |= BIT(0); - need_locked_scan_mode = 1; - } else { - CPRINTS("Heatmap disabled"); - } - - if (new_state & SYSTEM_STATE_ENABLE_DOME_SWITCH) - tx_buf[2] |= BIT(1); - ret = spi_transaction(SPI, tx_buf, sizeof(tx_buf), NULL, 0); - if (ret) - return ret; - set_bits(&system_state, new_state, mask); - } - - mask = SYSTEM_STATE_ACTIVE_MODE; - if ((new_state & mask) != (system_state & mask)) { - uint8_t tx_buf[] = { - ST_TP_CMD_WRITE_SCAN_MODE_SELECT, - ST_TP_SCAN_MODE_ACTIVE, - !!(new_state & SYSTEM_STATE_ACTIVE_MODE), - }; - CPRINTS("Enable Multi-Touch: %d", tx_buf[2]); - ret = spi_transaction(SPI, tx_buf, sizeof(tx_buf), NULL, 0); - if (ret) - return ret; - set_bits(&system_state, new_state, mask); - } - - /* - * We need to lock scan mode to prevent scan rate drop when heat map - * mode is enabled. - */ - if (need_locked_scan_mode) { - uint8_t tx_buf[] = { - ST_TP_CMD_WRITE_SCAN_MODE_SELECT, - ST_TP_SCAN_MODE_LOCKED, - 0x0, - }; - - ret = spi_transaction(SPI, tx_buf, sizeof(tx_buf), NULL, 0); - if (ret) - return ret; - } - return ret; -} - -static void st_tp_enable_interrupt(int enable) -{ - uint8_t tx_buf[] = { - ST_TP_CMD_WRITE_SYSTEM_COMMAND, 0x01, enable ? 1 : 0}; - if (enable) - gpio_enable_interrupt(GPIO_TOUCHPAD_INT); - spi_transaction(SPI, tx_buf, sizeof(tx_buf), NULL, 0); - if (!enable) - gpio_disable_interrupt(GPIO_TOUCHPAD_INT); -} - -static int st_tp_start_scan(void) -{ - int new_state = (SYSTEM_STATE_ACTIVE_MODE | - SYSTEM_STATE_ENABLE_DOME_SWITCH); - int mask = new_state; - int ret; - - CPRINTS("ST: Start scanning"); - ret = st_tp_update_system_state(new_state, mask); - if (ret) - return ret; - st_tp_send_ack(); - st_tp_enable_interrupt(1); - - return ret; -} - -static int st_tp_read_host_data_memory(uint16_t addr, void *rx_buf, int len) -{ - uint8_t tx_buf[] = { - ST_TP_CMD_READ_HOST_DATA_MEMORY, addr >> 8, addr & 0xFF - }; - - return spi_transaction(SPI, tx_buf, sizeof(tx_buf), rx_buf, len); -} - -static int st_tp_stop_scan(void) -{ - int new_state = 0; - int mask = SYSTEM_STATE_ACTIVE_MODE; - int ret; - - CPRINTS("ST: Stop scanning"); - ret = st_tp_update_system_state(new_state, mask); - st_tp_enable_interrupt(0); - - return ret; -} - -static int st_tp_load_host_data(uint8_t mem_id) -{ - uint8_t tx_buf[] = { - ST_TP_CMD_WRITE_SYSTEM_COMMAND, 0x06, mem_id - }; - int retry, ret; - uint16_t count; - struct st_tp_host_data_header_t *header = &rx_buf.data_header; - int rx_len = sizeof(*header) + ST_TP_DUMMY_BYTE; - - st_tp_read_host_data_memory(0x0000, &rx_buf, rx_len); - if (header->host_data_mem_id == mem_id) - return EC_SUCCESS; /* already loaded no need to reload */ - - count = header->count; - - ret = spi_transaction(SPI, tx_buf, sizeof(tx_buf), NULL, 0); - if (ret) - return ret; - - ret = EC_ERROR_TIMEOUT; - retry = 5; - while (retry--) { - st_tp_read_host_data_memory(0x0000, &rx_buf, rx_len); - if (header->magic == ST_TP_HEADER_MAGIC && - header->host_data_mem_id == mem_id && - header->count != count) { - ret = EC_SUCCESS; - break; - } - msleep(10); - } - return ret; -} - -/* - * Read System Info from Host Data Memory. - * - * @param reload: true to force reloading system info into host data memory - * before reading. - */ -static int st_tp_read_system_info(int reload) -{ - int ret = EC_SUCCESS; - int rx_len = ST_TP_DUMMY_BYTE + ST_TP_SYSTEM_INFO_LEN; - uint8_t *ptr = rx_buf.bytes; - - if (reload) - ret = st_tp_load_host_data(ST_TP_MEM_ID_SYSTEM_INFO); - if (ret) - return ret; - ret = st_tp_read_host_data_memory(0x0000, &rx_buf, rx_len); - if (ret) - return ret; - - /* Parse the content */ - memcpy(&system_info, ptr, ST_TP_SYSTEM_INFO_PART_1_SIZE); - - /* Check header */ - if (system_info.header.magic != ST_TP_HEADER_MAGIC || - system_info.header.host_data_mem_id != ST_TP_MEM_ID_SYSTEM_INFO) - return EC_ERROR_UNKNOWN; - - ptr += ST_TP_SYSTEM_INFO_PART_1_SIZE; - ptr += ST_TP_SYSTEM_INFO_PART_1_RESERVED; - memcpy(&system_info.scr_res_x, ptr, ST_TP_SYSTEM_INFO_PART_2_SIZE); - -#define ST_TP_SHOW(attr) CPRINTS(#attr ": %04x", system_info.attr) - ST_TP_SHOW(chip0_id[0]); - ST_TP_SHOW(chip0_id[1]); - ST_TP_SHOW(chip0_ver); - ST_TP_SHOW(scr_tx_len); - ST_TP_SHOW(scr_rx_len); -#define ST_TP_SHOW64(attr) CPRINTS(#attr ": %04llx", system_info.attr) - ST_TP_SHOW64(release_info); -#undef ST_TP_SHOW -#undef ST_TP_SHOW64 - return ret; -} - -/* - * Enable / disable deep sleep on memory and bus. - * - * Before calling dump_error() and dump_error(), deep sleep should be disabled, - * otherwise response data might be garbage. - */ -static void enable_deep_sleep(int enable) -{ - uint8_t cmd[] = {0xFA, 0x20, 0x00, 0x00, 0x68, enable ? 0x0B : 0x08}; - - spi_transaction(SPI, cmd, sizeof(cmd), NULL, 0); -} - -static void dump_error(void) -{ - uint8_t tx_buf[] = {0xFB, 0x20, 0x01, 0xEF, 0x80}; - int rx_len = sizeof(rx_buf.dump_info) + ST_TP_DUMMY_BYTE; - int i; - - spi_transaction(SPI, tx_buf, sizeof(tx_buf), - (uint8_t *)&rx_buf, rx_len); - - for (i = 0; i < ARRAY_SIZE(rx_buf.dump_info); i += 4) - CPRINTS("%08x %08x %08x %08x", - rx_buf.dump_info[i + 0], rx_buf.dump_info[i + 1], - rx_buf.dump_info[i + 2], rx_buf.dump_info[i + 3]); - msleep(8); -} - -/* - * Dump entire 64K memory on touchpad. - * - * This is very time consuming. For now, let's disable this in production - * build. - */ -static void dump_memory(void) -{ - uint32_t size = 0x10000, rx_len = 512 + ST_TP_DUMMY_BYTE; - uint32_t offset, i; - uint8_t cmd[] = {0xFB, 0x00, 0x10, 0x00, 0x00}; - - if (!dump_memory_on_error) - return; - - for (offset = 0; offset < size; offset += 512) { - cmd[3] = (offset >> 8) & 0xFF; - cmd[4] = (offset >> 0) & 0xFF; - spi_transaction(SPI, cmd, sizeof(cmd), - (uint8_t *)&rx_buf, rx_len); - - for (i = 0; i < rx_len - ST_TP_DUMMY_BYTE; i += 32) { - CPRINTF("%ph %ph %ph %ph " - "%ph %ph %ph %ph\n", - HEX_BUF(rx_buf.bytes + i + 4 * 0, 4), - HEX_BUF(rx_buf.bytes + i + 4 * 1, 4), - HEX_BUF(rx_buf.bytes + i + 4 * 2, 4), - HEX_BUF(rx_buf.bytes + i + 4 * 3, 4), - HEX_BUF(rx_buf.bytes + i + 4 * 4, 4), - HEX_BUF(rx_buf.bytes + i + 4 * 5, 4), - HEX_BUF(rx_buf.bytes + i + 4 * 6, 4), - HEX_BUF(rx_buf.bytes + i + 4 * 7, 4)); - msleep(8); - } - } - CPRINTF("===============================\n"); - msleep(8); -} - -/* - * Set `tp_control` if there are any actions should be taken. - */ -static void st_tp_handle_error(uint8_t error_type) -{ - tp_control |= TP_CONTROL_SHALL_DUMP_ERROR; - - /* - * Suggest action: memory dump and power cycle. - */ - if (error_type <= 0x06 || - error_type == 0xF1 || - error_type == 0xF2 || - error_type == 0xF3 || - (error_type >= 0x47 && error_type <= 0x4E)) { - tp_control |= TP_CONTROL_SHALL_RESET; - return; - } - - /* - * Suggest action: FW shall halt, consult ST. - */ - if ((error_type >= 0x20 && error_type <= 0x23) || - error_type == 0x25 || - (error_type >= 0x2E && error_type <= 0x46)) { - CPRINTS("tp shall halt"); - tp_control |= TP_CONTROL_SHALL_HALT; - return; - } - - /* - * Corrupted panel configuration, a panel init should fix it. - */ - if (error_type >= 0x28 && error_type <= 0x29) { - tp_control |= TP_CONTROL_SHALL_INIT; - return; - } - - /* - * Corrupted CX section, a full panel init should fix it. - */ - if (error_type >= 0xA0 && error_type <= 0xA6) { - tp_control |= TP_CONTROL_SHALL_INIT_FULL; - return; - } - - /* - * When 0xFF is received, it's very likely ST touchpad is down. - * Try if touchpad can be recovered by reset. - */ - if (error_type == 0xFF) { - if (tp_reset_retry_count < MAX_TP_RESET_RETRY_COUNT) { - tp_control |= TP_CONTROL_SHALL_RESET; - tp_reset_retry_count++; - } else { - tp_control |= TP_CONTROL_SHALL_HALT; - } - return; - } -} - -/* - * Handles error reports. - */ -static void st_tp_handle_error_report(struct st_tp_event_t *e) -{ - uint8_t error_type = e->report.report_type; - - CPRINTS("Touchpad error: %x %x", error_type, - ((e->report.info[0] << 0) | (e->report.info[1] << 8) | - (e->report.info[2] << 16) | (e->report.info[3] << 24))); - - st_tp_handle_error(error_type); -} - -static void st_tp_handle_status_report(struct st_tp_event_t *e) -{ - static uint32_t prev_idle_count; - uint32_t info = ((e->report.info[0] << 0) | - (e->report.info[1] << 8) | - (e->report.info[2] << 16) | - (e->report.info[3] << 24)); - - if (e->report.report_type == ST_TP_STATUS_FCAL || - e->report.report_type == ST_TP_STATUS_FRAME_DROP) - CPRINTS("TP STATUS REPORT: %02x %08x", - e->report.report_type, info); - - /* - * Idle count might not change if ST FW is busy (for example, when the - * user puts a big palm on touchpad). Therefore if idle count doesn't - * change, we need to double check with touch count. - * - * If touch count is 0, and idle count doesn't change, it means that: - * - * 1) ST doesn't think there are any fingers. - * 2) ST is busy on something, can't get into idle mode, and this - * might cause (1). - * - * Resetting touchpad should be the correct action. - */ - if (e->report.report_type == ST_TP_STATUS_BEACON) { -#if 0 - const uint8_t touch_count = e->report.reserved; - - CPRINTS("BEACON: idle count=%08x", info); - CPRINTS(" touch count=%d touch slot=%04x", - touch_count, touch_slot); -#endif - if (prev_idle_count == info && touch_slot == 0) { - CPRINTS(" idle count=%08x not changed", info); - tp_control |= TP_CONTROL_SHALL_RESET; - return; - } - prev_idle_count = info; - } -} - -/* - * Read all events, and handle errors. - * - * When there are error events, suggested action will be saved in `tp_control`. - * - * @param show_error: weather EC should read and dump error or not. - * ***If this is true, rx_buf.events[] will be cleared.*** - * - * @return number of events available - */ -static int st_tp_read_all_events(int show_error) -{ - uint8_t cmd = ST_TP_CMD_READ_ALL_EVENTS; - int rx_len = sizeof(rx_buf.events) + ST_TP_DUMMY_BYTE; - int i; - - if (spi_transaction(SPI, &cmd, 1, (uint8_t *)&rx_buf, rx_len)) - return 0; - - for (i = 0; i < ARRAY_SIZE(rx_buf.events); i++) { - struct st_tp_event_t *e = &rx_buf.events[i]; - - if (e->magic != ST_TP_EVENT_MAGIC) - break; - - switch (e->evt_id) { - case ST_TP_EVENT_ID_ERROR_REPORT: - st_tp_handle_error_report(e); - break; - case ST_TP_EVENT_ID_STATUS_REPORT: - st_tp_handle_status_report(e); - break; - } - } - - if (show_error && (tp_control & TP_CONTROL_SHALL_DUMP_ERROR)) { - enable_deep_sleep(0); - dump_error(); - dump_memory(); - enable_deep_sleep(1); - /* rx_buf.events[] is invalid now */ - i = 0; - } - tp_control &= ~TP_CONTROL_SHALL_DUMP_ERROR; - - return i; -} - -/* - * Reset touchpad. This function will wait for "controller ready" event after - * the touchpad is reset. - */ -static int st_tp_reset(void) -{ - int i, num_events, retry = 100; - - board_touchpad_reset(); - - while (retry--) { - num_events = st_tp_read_all_events(0); - - /* - * We are not doing full panel initialization, and error code - * suggest us to reset or halt. - */ - if (!(tp_control & (TP_CONTROL_INIT | TP_CONTROL_INIT_FULL)) && - (tp_control & (TP_CONTROL_SHALL_HALT | - TP_CONTROL_SHALL_RESET))) - break; - - for (i = 0; i < num_events; i++) { - struct st_tp_event_t *e = &rx_buf.events[i]; - - if (e->evt_id == ST_TP_EVENT_ID_CONTROLLER_READY) { - CPRINTS("Touchpad ready"); - tp_reset_retry_count = 0; - return 0; - } - } - - msleep(10); - } - CPRINTS("Timeout waiting for controller ready."); - return EC_ERROR_TIMEOUT; -} - -/* Initialize the controller ICs after reset */ -static void st_tp_init(void) -{ - tp_control = 0; - system_state = 0; - - if (st_tp_reset()) - return; - - if (tp_control) { - CPRINTS("tp_control = %x", tp_control); - return; - } - /* - * On boot, ST firmware will load system info to host data memory, - * So we don't need to reload it. - */ - st_tp_read_system_info(0); - - system_state = SYSTEM_STATE_READY; - touch_slot = 0; - - touchpad_power_control(); -} -DECLARE_DEFERRED(st_tp_init); - -#ifdef CONFIG_USB_UPDATE -int touchpad_get_info(struct touchpad_info *tp) -{ - if (st_tp_read_system_info(1)) { - tp->status = EC_RES_SUCCESS; - tp->vendor = ST_VENDOR_ID; - /* - * failed to get system info, FW corrupted, return some default - * values. - */ - tp->st.id = 0x3936; - tp->st.fw_version = 0; - tp->st.fw_checksum = 0; - return sizeof(*tp); - } - - tp->status = EC_RES_SUCCESS; - tp->vendor = ST_VENDOR_ID; - tp->st.id = (system_info.chip0_id[0] << 8) | system_info.chip0_id[1]; - tp->st.fw_version = system_info.release_info; - tp->st.fw_checksum = system_info.fw_crc; - - return sizeof(*tp); -} - -/* - * Helper functions for firmware update - * - * There is no documentation about ST_TP_CMD_WRITE_HW_REG (0xFA). - * All implementations below are based on sample code from ST. - */ -static int write_hwreg_cmd32(uint32_t address, uint32_t data) -{ - uint8_t tx_buf[] = { - ST_TP_CMD_WRITE_HW_REG, - (address >> 24) & 0xFF, - (address >> 16) & 0xFF, - (address >> 8) & 0xFF, - (address >> 0) & 0xFF, - (data >> 24) & 0xFF, - (data >> 16) & 0xFF, - (data >> 8) & 0xFF, - (data >> 0) & 0xFF, - }; - - return spi_transaction(SPI, tx_buf, sizeof(tx_buf), NULL, 0); -} - -static int write_hwreg_cmd8(uint32_t address, uint8_t data) -{ - uint8_t tx_buf[] = { - ST_TP_CMD_WRITE_HW_REG, - (address >> 24) & 0xFF, - (address >> 16) & 0xFF, - (address >> 8) & 0xFF, - (address >> 0) & 0xFF, - data, - }; - - return spi_transaction(SPI, tx_buf, sizeof(tx_buf), NULL, 0); -} - -static int wait_for_flash_ready(uint8_t type) -{ - uint8_t tx_buf[] = { - ST_TP_CMD_READ_HW_REG, - 0x20, 0x00, 0x00, type, - }; - int ret = EC_SUCCESS, retry = 200; - - while (retry--) { - ret = spi_transaction(SPI, tx_buf, sizeof(tx_buf), - (uint8_t *)&rx_buf, 1 + ST_TP_DUMMY_BYTE); - if (ret == EC_SUCCESS && !(rx_buf.bytes[0] & 0x80)) - break; - msleep(50); - } - return retry >= 0 ? ret : EC_ERROR_TIMEOUT; -} - -static int erase_flash(int full_init_required) -{ - int ret; - - if (full_init_required) - ret = write_hwreg_cmd32(0x20000128, 0xFFFFFFFF); - else - /* Erase everything, except CX */ - ret = write_hwreg_cmd32(0x20000128, 0xFFFFFF83); - if (ret) - return ret; - ret = write_hwreg_cmd8(0x2000006B, 0x00); - if (ret) - return ret; - ret = write_hwreg_cmd8(0x2000006A, 0xA0); - if (ret) - return ret; - return wait_for_flash_ready(0x6A); -} - -static int st_tp_prepare_for_update(int full_init_required) -{ - /* hold m3 */ - write_hwreg_cmd8(0x20000024, 0x01); - /* unlock flash */ - write_hwreg_cmd8(0x20000025, 0x20); - /* unlock flash erase */ - write_hwreg_cmd8(0x200000DE, 0x03); - erase_flash(full_init_required); - - return EC_SUCCESS; -} - -static int st_tp_start_flash_dma(void) -{ - int ret; - - ret = write_hwreg_cmd8(0x20000071, 0xC0); - if (ret) - return ret; - ret = wait_for_flash_ready(0x71); - return ret; -} - -static int st_tp_write_one_chunk(const uint8_t *head, - uint32_t addr, uint32_t chunk_size) -{ - uint8_t tx_buf[ST_TP_DMA_CHUNK_SIZE + 5]; - uint32_t index = 0; - int ret; - - index = 0; - - tx_buf[index++] = ST_TP_CMD_WRITE_HW_REG; - tx_buf[index++] = (addr >> 24) & 0xFF; - tx_buf[index++] = (addr >> 16) & 0xFF; - tx_buf[index++] = (addr >> 8) & 0xFF; - tx_buf[index++] = (addr >> 0) & 0xFF; - memcpy(tx_buf + index, head, chunk_size); - ret = spi_transaction(SPI, tx_buf, chunk_size + 5, NULL, 0); - - return ret; -} - -/* - * @param offset: offset in memory to copy the data (in bytes). - * @param size: length of data (in bytes). - * @param data: pointer to data bytes. - */ -static int st_tp_write_flash(int offset, int size, const uint8_t *data) -{ - uint8_t tx_buf[12] = {0}; - const uint8_t *head = data, *tail = data + size; - uint32_t addr, index, chunk_size; - uint32_t flash_buffer_size; - int ret; - - offset >>= 2; /* offset should be count in words */ - /* - * To write to flash, the data has to be separated into several chunks. - * Each chunk will be no more than `ST_TP_DMA_CHUNK_SIZE` bytes. - * The chunks will first be saved into a buffer, the buffer can only - * holds `ST_TP_FLASH_BUFFER_SIZE` bytes. We have to flush the buffer - * when the capacity is reached. - */ - while (head < tail) { - addr = 0x00100000; - flash_buffer_size = 0; - while (flash_buffer_size < ST_TP_FLASH_BUFFER_SIZE) { - chunk_size = MIN(ST_TP_DMA_CHUNK_SIZE, tail - head); - ret = st_tp_write_one_chunk(head, addr, chunk_size); - if (ret) - return ret; - - flash_buffer_size += chunk_size; - addr += chunk_size; - head += chunk_size; - - if (head >= tail) - break; - } - - /* configuring the DMA */ - flash_buffer_size = flash_buffer_size / 4 - 1; - index = 0; - - tx_buf[index++] = ST_TP_CMD_WRITE_HW_REG; - tx_buf[index++] = 0x20; - tx_buf[index++] = 0x00; - tx_buf[index++] = 0x00; - tx_buf[index++] = 0x72; /* flash DMA config */ - tx_buf[index++] = 0x00; - tx_buf[index++] = 0x00; - - tx_buf[index++] = offset & 0xFF; - tx_buf[index++] = (offset >> 8) & 0xFF; - tx_buf[index++] = flash_buffer_size & 0xFF; - tx_buf[index++] = (flash_buffer_size >> 8) & 0xFF; - tx_buf[index++] = 0x00; - - ret = spi_transaction(SPI, tx_buf, index, NULL, 0); - if (ret) - return ret; - ret = st_tp_start_flash_dma(); - if (ret) - return ret; - - offset += ST_TP_FLASH_BUFFER_SIZE / 4; - } - return EC_SUCCESS; -} - -static int st_tp_check_command_echo(const uint8_t *cmd, const size_t len) -{ - int num_events, i; - num_events = st_tp_read_all_events(0); - - for (i = 0; i < num_events; i++) { - struct st_tp_event_t *e = &rx_buf.events[i]; - - if (e->evt_id == ST_TP_EVENT_ID_STATUS_REPORT && - e->report.report_type == ST_TP_STATUS_CMD_ECHO && - memcmp(e->report.info, cmd, MIN(4, len)) == 0) - return EC_SUCCESS; - } - return EC_ERROR_BUSY; -} - -static uint8_t get_cx_version(uint8_t tp_version) -{ - /* - * CX version is tracked by ST release note: go/whiskers-st-release-note - */ - - if (tp_version >= 32) - return 3; - - if (tp_version >= 20) - return 2; - - if (tp_version >= 18) - return 1; - return 0; -} - -/* - * Perform panel initialization. - * - * This function will wait until the initialization is done, or 10 second - * timeout is reached. - * - * @param full: 1 => force "full" panel initialization. Otherwise, tp_control - * will be checked to decide if full panel initialization is - * required. - * - * @return EC_SUCCESS or error code. - */ -static int st_tp_panel_init(int full) -{ - uint8_t tx_buf[] = { - ST_TP_CMD_WRITE_SYSTEM_COMMAND, 0x00, 0x02 - }; - int ret, retry; - - if (tp_control & (TP_CONTROL_INIT | TP_CONTROL_INIT_FULL)) - return EC_ERROR_BUSY; - - st_tp_stop_scan(); - ret = st_tp_reset(); - /* - * TODO(b:118312397): Figure out how to handle st_tp_reset errors (if - * needed at all). - */ - CPRINTS("st_tp_reset ret=%d", ret); - - full |= tp_control & TP_CONTROL_SHALL_INIT_FULL; - if (full) { - /* should perform full panel initialization */ - tx_buf[2] = 0x3; - tp_control = TP_CONTROL_INIT_FULL; - } else { - tp_control = TP_CONTROL_INIT; - } - - CPRINTS("Start panel initialization (full=%d)", full); - spi_transaction(SPI, tx_buf, sizeof(tx_buf), NULL, 0); - - retry = 100; - while (retry--) { - watchdog_reload(); - msleep(100); - - ret = st_tp_check_command_echo(tx_buf, sizeof(tx_buf)); - if (ret == EC_SUCCESS) { - CPRINTS("Panel initialization completed."); - tp_control &= ~(TP_CONTROL_INIT | TP_CONTROL_INIT_FULL); - st_tp_init(); - return EC_SUCCESS; - } else if (ret == EC_ERROR_BUSY) { - CPRINTS("Panel initialization on going..."); - } else if (tp_control & ~(TP_CONTROL_INIT | - TP_CONTROL_INIT_FULL)) { - /* there are other kind of errors. */ - CPRINTS("Panel initialization failed, tp_control: %x", - tp_control); - return EC_ERROR_UNKNOWN; - } - } - return EC_ERROR_TIMEOUT; -} - -/* - * @param offset: should be address between 0 to 1M, aligned with - * ST_TP_DMA_CHUNK_SIZE. - * @param size: length of `data` array. - * @param data: content of new touchpad firmware. - */ -int touchpad_update_write(int offset, int size, const uint8_t *data) -{ - static int full_init_required; - int ret, flash_offset; - - CPRINTS("%s %08x %d", __func__, offset, size); - if (offset == 0) { - const struct st_tp_fw_header_t *header; - uint8_t old_cx_version; - uint8_t new_cx_version; - int retry; - - header = (const struct st_tp_fw_header_t *)data; - if (header->signature != 0xAA55AA55) - return EC_ERROR_INVAL; - - for (retry = 50; retry > 0; retry--) { - watchdog_reload(); - if (system_state & SYSTEM_STATE_READY) - break; - if (retry % 10 == 0) - CPRINTS("TP not ready for update, " - "will check again"); - msleep(100); - } - - old_cx_version = get_cx_version(system_info.release_info); - new_cx_version = get_cx_version(header->release_info); - - full_init_required = old_cx_version != new_cx_version; - - /* stop scanning, interrupt, etc... */ - st_tp_stop_scan(); - - ret = st_tp_prepare_for_update(full_init_required); - if (ret) - return ret; - return EC_SUCCESS; - } - - flash_offset = offset - CONFIG_UPDATE_PDU_SIZE; - if (flash_offset % ST_TP_DMA_CHUNK_SIZE) - return EC_ERROR_INVAL; - - if (flash_offset >= ST_TP_FLASH_OFFSET_PANEL_CFG && - flash_offset < ST_TP_FLASH_OFFSET_CONFIG) - /* don't update CX section && panel config section */ - return EC_SUCCESS; - - ret = st_tp_write_flash(flash_offset, size, data); - if (ret) - return ret; - - if (offset + size == CONFIG_TOUCHPAD_VIRTUAL_SIZE) { - CPRINTS("%s: End update, wait for reset.", __func__); - - ret = st_tp_panel_init(full_init_required); - task_set_event(TASK_ID_TOUCHPAD, TASK_EVENT_TP_UPDATED, 0); - return ret; - } - - return EC_SUCCESS; -} - -int touchpad_debug(const uint8_t *param, unsigned int param_size, - uint8_t **data, unsigned int *data_size) -{ - static uint8_t buf[8]; - int num_events; - - if (param_size != 1) - return EC_RES_INVALID_PARAM; - - switch (*param) { - case ST_TP_DEBUG_CMD_RESET_TOUCHPAD: - *data = NULL; - *data_size = 0; - st_tp_stop_scan(); - hook_call_deferred(&st_tp_init_data, 100 * MSEC); - return EC_SUCCESS; - case ST_TP_DEBUG_CMD_CALIBRATE: - /* no return value */ - *data = NULL; - *data_size = 0; - st_tp_panel_init(1); - return EC_SUCCESS; - case ST_TP_DEBUG_CMD_START_SCAN: - *data = NULL; - *data_size = 0; - st_tp_start_scan(); - return EC_SUCCESS; - case ST_TP_DEBUG_CMD_STOP_SCAN: - *data = NULL; - *data_size = 0; - st_tp_stop_scan(); - return EC_SUCCESS; - case ST_TP_DEBUG_CMD_READ_BUF_HEADER: - *data = buf; - *data_size = 8; - st_tp_read_host_buffer_header(); - memcpy(buf, rx_buf.bytes, *data_size); - CPRINTS("header: %ph", HEX_BUF(buf, *data_size)); - return EC_SUCCESS; - case ST_TP_DEBUG_CMD_READ_EVENTS: - num_events = st_tp_read_all_events(0); - if (num_events) { - int i; - - for (i = 0; i < num_events; i++) { - CPRINTS("event[%d]: id=%d, type=%d", - i, rx_buf.events[i].evt_id, - rx_buf.events[i].report.report_type); - } - } - *data = buf; - *data_size = 1; - *data[0] = num_events; - st_tp_send_ack(); - return EC_SUCCESS; - } - return EC_RES_INVALID_PARAM; -} -#endif - -void touchpad_interrupt(enum gpio_signal signal) -{ - irq_ts = __hw_clock_source_read(); - - task_wake(TASK_ID_TOUCHPAD); -} - -static int touchpad_should_enable(void) -{ - /* touchpad is not ready. */ - if (tp_control) - return 0; - -#ifdef CONFIG_USB_SUSPEND - if (usb_is_suspended() && !usb_is_remote_wakeup_enabled()) - return 0; -#endif - -#ifdef CONFIG_TABLET_MODE - if (tablet_get_mode()) - return 0; -#endif - return 1; -} - -/* Make a decision on touchpad power, based on USB and tablet mode status. */ -static void touchpad_power_control(void) -{ - const int enabled = !!(system_state & SYSTEM_STATE_ACTIVE_MODE); - int enable = touchpad_should_enable(); - - if (enabled == enable) - return; - - if (enable) - st_tp_start_scan(); - else - st_tp_stop_scan(); -} - -static void touchpad_read_idle_count(void) -{ - static uint32_t prev_count; - uint32_t count; - int ret; - int rx_len = 2 + ST_TP_DUMMY_BYTE; - uint8_t cmd_read_counter[] = { - 0xFB, 0x00, 0x10, 0xff, 0xff - }; - - /* Find address of idle count. */ - ret = st_tp_load_host_data(ST_TP_MEM_ID_SYSTEM_INFO); - if (ret) - return; - st_tp_read_host_data_memory(0x0082, &rx_buf, rx_len); - - /* Fill in address of idle count, the byte order is reversed. */ - cmd_read_counter[3] = rx_buf.bytes[1]; - cmd_read_counter[4] = rx_buf.bytes[0]; - - /* Read idle count */ - spi_transaction(SPI, cmd_read_counter, sizeof(cmd_read_counter), - (uint8_t *)&rx_buf, 4 + ST_TP_DUMMY_BYTE); - - count = rx_buf.dump_info[0]; - - CPRINTS("idle_count = %08x", count); - if (count == prev_count) - CPRINTS("counter doesn't change..."); - else - prev_count = count; -} - -/* - * Try to collect symptoms of type B error. - * - * There are three possible symptoms: - * 1. error dump section is corrupted / contains error. - * 2. memory stack is corrupted (not 0xCC). - * 3. idle count is not changing. - */ -static void touchpad_collect_error(void) -{ - const uint8_t tx_dump_error[] = { - 0xFB, 0x20, 0x01, 0xEF, 0x80 - }; - uint32_t dump_info[2]; - const uint8_t tx_dump_memory[] = { - 0xFB, 0x00, 0x10, 0x00, 0x00 - }; - uint32_t dump_memory[16]; - int i; - - enable_deep_sleep(0); - spi_transaction(SPI, tx_dump_error, sizeof(tx_dump_error), - (uint8_t *)&rx_buf, - sizeof(dump_info) + ST_TP_DUMMY_BYTE); - memcpy(dump_info, rx_buf.bytes, sizeof(dump_info)); - - spi_transaction(SPI, tx_dump_memory, sizeof(tx_dump_memory), - (uint8_t *)&rx_buf, - sizeof(dump_memory) + ST_TP_DUMMY_BYTE); - memcpy(dump_memory, rx_buf.bytes, sizeof(dump_memory)); - - CPRINTS("check error dump: %08x %08x", dump_info[0], dump_info[1]); - CPRINTS("check memory dump:"); - for (i = 0; i < ARRAY_SIZE(dump_memory); i += 8) { - CPRINTF("%08x %08x %08x %08x %08x %08x %08x %08x\n", - dump_memory[i + 0], - dump_memory[i + 1], - dump_memory[i + 2], - dump_memory[i + 3], - dump_memory[i + 4], - dump_memory[i + 5], - dump_memory[i + 6], - dump_memory[i + 7]); - } - - for (i = 0; i < 3; i++) - touchpad_read_idle_count(); - enable_deep_sleep(1); - - tp_control |= TP_CONTROL_SHALL_RESET; -} - -void touchpad_task(void *u) -{ - uint32_t event; - - while (1) { - uint32_t retry; - - for (retry = 0; retry < 3; retry++) { - CPRINTS("st_tp_init: trial %d", retry + 1); - st_tp_init(); - - if (system_state & SYSTEM_STATE_READY) - break; - /* - * React on touchpad errors. - */ - if (tp_control & TP_CONTROL_SHALL_INIT_FULL) { - /* suppress other handlers */ - tp_control = TP_CONTROL_SHALL_INIT_FULL; - st_tp_panel_init(1); - } else if (tp_control & TP_CONTROL_SHALL_INIT) { - /* suppress other handlers */ - tp_control = TP_CONTROL_SHALL_INIT; - st_tp_panel_init(0); - } else if (tp_control & TP_CONTROL_SHALL_RESET) { - /* suppress other handlers */ - tp_control = TP_CONTROL_SHALL_RESET; - } else if (tp_control & TP_CONTROL_SHALL_HALT) { - CPRINTS("shall halt"); - tp_control = 0; - break; - } - } - - if (system_state & SYSTEM_STATE_READY) - break; - - /* failed to init, mark it as ready to allow upgrade */ - system_state = SYSTEM_STATE_READY; - /* wait for upgrade complete */ - task_wait_event_mask(TASK_EVENT_TP_UPDATED, -1); - } - touchpad_power_control(); - - while (1) { - /* wait for at most 3 seconds */ - event = task_wait_event(3 * 1000 * 1000); - - if ((event & TASK_EVENT_TIMER) && - (system_state & SYSTEM_STATE_ACTIVE_MODE)) - /* - * Haven't received anything for 3 seconds, and we are - * supposed to be in active mode. This is not normal, - * check for errors and reset. - */ - touchpad_collect_error(); - - if (event & TASK_EVENT_WAKE) - while (!tp_control && - !gpio_get_level(GPIO_TOUCHPAD_INT)) - st_tp_read_report(); - - /* - * React on touchpad errors. - */ - if (tp_control & TP_CONTROL_SHALL_INIT_FULL) { - /* suppress other handlers */ - tp_control = TP_CONTROL_SHALL_INIT_FULL; - st_tp_panel_init(1); - } else if (tp_control & TP_CONTROL_SHALL_INIT) { - /* suppress other handlers */ - tp_control = TP_CONTROL_SHALL_INIT; - st_tp_panel_init(0); - } else if (tp_control & TP_CONTROL_SHALL_RESET) { - /* suppress other handlers */ - tp_control = TP_CONTROL_SHALL_RESET; - st_tp_init(); - } else if (tp_control & TP_CONTROL_SHALL_HALT) { - tp_control = 0; - st_tp_stop_scan(); - } - - if (event & TASK_EVENT_POWER) - touchpad_power_control(); - } -} - -/* - * When USB PM status changes, or tablet mode changes, call in the main task to - * decide whether to turn touchpad on or off. - */ -#if defined(CONFIG_USB_SUSPEND) || defined(CONFIG_TABLET_MODE) -static void touchpad_power_change(void) -{ - task_set_event(TASK_ID_TOUCHPAD, TASK_EVENT_POWER, 0); -} -#endif -#ifdef CONFIG_USB_SUSPEND -DECLARE_HOOK(HOOK_USB_PM_CHANGE, touchpad_power_change, HOOK_PRIO_DEFAULT); -#endif -#ifdef CONFIG_TABLET_MODE -DECLARE_HOOK(HOOK_TABLET_MODE_CHANGE, touchpad_power_change, HOOK_PRIO_DEFAULT); -#endif - -#ifdef CONFIG_USB_ISOCHRONOUS -static void st_tp_enable_heat_map(void) -{ - int new_state = (SYSTEM_STATE_ENABLE_HEAT_MAP | - SYSTEM_STATE_ENABLE_DOME_SWITCH | - SYSTEM_STATE_ACTIVE_MODE); - int mask = new_state; - - st_tp_update_system_state(new_state, mask); -} -DECLARE_DEFERRED(st_tp_enable_heat_map); - -static void st_tp_disable_heat_map(void) -{ - int new_state = 0; - int mask = SYSTEM_STATE_ENABLE_HEAT_MAP; - - st_tp_update_system_state(new_state, mask); -} -DECLARE_DEFERRED(st_tp_disable_heat_map); - -static void print_frame(void) -{ - char debug_line[ST_TOUCH_COLS + 5]; - int i, j, index; - int v; - struct st_tp_usb_packet_t *packet = &usb_packet[usb_buffer_index & 1]; - - if (usb_buffer_index == spi_buffer_index) - /* buffer is empty. */ - return; - - /* We will have ~150 FPS, let's print ~4 frames per second */ - if (usb_buffer_index % 37 == 0) { - /* move cursor back to top left corner */ - CPRINTF("\x1b[H"); - CPUTS("==============\n"); - for (i = 0; i < ST_TOUCH_ROWS; i++) { - for (j = 0; j < ST_TOUCH_COLS; j++) { - index = i * ST_TOUCH_COLS; - index += (ST_TOUCH_COLS - j - 1); // flip X - v = packet->frame[index]; - - if (v > 0) - debug_line[j] = '0' + v * 10 / 256; - else - debug_line[j] = ' '; - } - debug_line[j++] = '\n'; - debug_line[j++] = '\0'; - CPRINTF(debug_line); - } - CPUTS("==============\n"); - } -} - -static int st_tp_read_frame(void) -{ - int ret = EC_SUCCESS; - int rx_len = ST_TOUCH_FRAME_SIZE + ST_TP_DUMMY_BYTE; - int heat_map_addr = get_heat_map_addr(); - uint8_t tx_buf[] = { - ST_TP_CMD_READ_SPI_HOST_BUFFER, - (heat_map_addr >> 8) & 0xFF, - (heat_map_addr >> 0) & 0xFF, - }; - - /* - * Since usb_packet.frame is already ane uint8_t byte array, we can just - * make it the RX buffer for SPI transaction. - * - * When there is a dummy byte, since we know that flags is a one byte - * value, and we will override it later, it's okay for SPI transaction - * to write the dummy byte to flags address. - */ -#if ST_TP_DUMMY_BYTE == 1 - BUILD_ASSERT(sizeof(usb_packet[0].flags) == 1); - uint8_t *rx_buf = &usb_packet[spi_buffer_index & 1].flags; -#else - uint8_t *rx_buf = usb_packet[spi_buffer_index & 1].frame; -#endif - - st_tp_read_all_events(1); - if (tp_control) { - ret = EC_ERROR_UNKNOWN; - goto failed; - } - - if (heat_map_addr < 0) - goto failed; - - ret = st_tp_check_domeswitch_state(); - if (ret) - goto failed; - - /* - * Theoretically, we should read host buffer header to check if data is - * valid, but the data should always be ready when interrupt pin is low. - * Let's skip this check for now. - */ - ret = spi_transaction(SPI, tx_buf, sizeof(tx_buf), - (uint8_t *)rx_buf, rx_len); - if (ret == EC_SUCCESS) { - int i; - uint8_t *dest = usb_packet[spi_buffer_index & 1].frame; - uint8_t max_value = 0; - - for (i = 0; i < ST_TOUCH_COLS * ST_TOUCH_ROWS; i++) - max_value |= dest[i]; - if (max_value == 0) // empty frame - return -1; - - usb_packet[spi_buffer_index & 1].flags = 0; - if (system_state & SYSTEM_STATE_DOME_SWITCH_LEVEL) - usb_packet[spi_buffer_index & 1].flags |= - USB_FRAME_FLAGS_BUTTON; - } -failed: - return ret; -} - -/* Define USB interface for heat_map */ - -/* function prototypes */ -static int st_tp_usb_set_interface(usb_uint alternate_setting, - usb_uint interface); -static int heatmap_send_packet(struct usb_isochronous_config const *config); -static void st_tp_usb_tx_callback(struct usb_isochronous_config const *config); - -/* USB descriptors */ -USB_ISOCHRONOUS_CONFIG_FULL(usb_st_tp_heatmap_config, - USB_IFACE_ST_TOUCHPAD, - USB_CLASS_VENDOR_SPEC, - USB_SUBCLASS_GOOGLE_HEATMAP, - USB_PROTOCOL_GOOGLE_HEATMAP, - USB_STR_HEATMAP_NAME, /* interface name */ - USB_EP_ST_TOUCHPAD, - USB_ISO_PACKET_SIZE, - st_tp_usb_tx_callback, - st_tp_usb_set_interface, - 1 /* 1 extra EP for interrupts */) - -/* ***This function will be executed in interrupt context*** */ -void st_tp_usb_tx_callback(struct usb_isochronous_config const *config) -{ - task_wake(TASK_ID_HEATMAP); -} - -void heatmap_task(void *unused) -{ - struct usb_isochronous_config const *config; - - config = &usb_st_tp_heatmap_config; - - while (1) { - /* waiting st_tp_usb_tx_callback() */ - task_wait_event(-1); - - if (system_state & SYSTEM_STATE_DEBUG_MODE) - continue; - - if (usb_buffer_index == spi_buffer_index) - /* buffer is empty */ - continue; - - while (heatmap_send_packet(config)) - /* We failed to write a packet, try again later. */ - task_wait_event(100); - } -} - -/* USB interface has completed TX, it's asking for more data */ -static int heatmap_send_packet(struct usb_isochronous_config const *config) -{ - size_t num_byte_available; - size_t offset = 0; - int ret, buffer_id = -1; - struct st_tp_usb_packet_t *packet = &usb_packet[usb_buffer_index & 1]; - - packet_header.flags = 0; - num_byte_available = sizeof(*packet) - transmit_report_offset; - if (num_byte_available > 0) { - if (transmit_report_offset == 0) - packet_header.flags |= HEADER_FLAGS_NEW_FRAME; - ret = usb_isochronous_write_buffer( - config, - (uint8_t *)&packet_header, - sizeof(packet_header), - offset, - &buffer_id, - 0); - /* - * Since USB_ISO_PACKET_SIZE > sizeof(packet_header), this must - * be true. - */ - if (ret != sizeof(packet_header)) - return -1; - - offset += ret; - packet_header.index++; - - ret = usb_isochronous_write_buffer( - config, - (uint8_t *)packet + transmit_report_offset, - num_byte_available, - offset, - &buffer_id, - 1); - if (ret < 0) { - /* - * TODO(b/70482333): handle this error, it might be: - * 1. timeout (buffer_id changed) - * 2. invalid offset - * - * For now, let's just return an error and try again. - */ - CPRINTS("%s %d: %d", __func__, __LINE__, -ret); - return ret; - } - - /* We should have sent some bytes, update offset */ - transmit_report_offset += ret; - if (transmit_report_offset == sizeof(*packet)) { - transmit_report_offset = 0; - usb_buffer_index++; - } - } - return 0; -} - -static int st_tp_usb_set_interface(usb_uint alternate_setting, - usb_uint interface) -{ - if (alternate_setting == 1) { - if ((system_info.release_info & 0xFF) < - ST_TP_MIN_HEATMAP_VERSION) { - CPRINTS("release version %04llx doesn't support heatmap", - system_info.release_info); - /* Heatmap mode is not supported in this version. */ - return -1; - } - - hook_call_deferred(&st_tp_enable_heat_map_data, 0); - return 0; - } else if (alternate_setting == 0) { - hook_call_deferred(&st_tp_disable_heat_map_data, 0); - return 0; - } else /* we only have two settings. */ - return -1; -} - -static int get_heat_map_addr(void) -{ - /* - * TODO(stimim): drop this when we are sure all trackpads are having the - * same config (e.g. after EVT). - */ - if (system_info.release_info >= 0x3) - return 0x0120; - else if (system_info.release_info == 0x1) - return 0x20; - else - return -1; /* Unknown version */ -} - -struct st_tp_interrupt_t { -#define ST_TP_INT_FRAME_AVAILABLE BIT(0) - uint8_t flags; -} __packed; - -static usb_uint st_tp_usb_int_buffer[ - DIV_ROUND_UP(sizeof(struct st_tp_interrupt_t), 2)] __usb_ram; - -const struct usb_endpoint_descriptor USB_EP_DESC(USB_IFACE_ST_TOUCHPAD, 81) = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = 0x80 | USB_EP_ST_TOUCHPAD_INT, - .bmAttributes = 0x03 /* Interrupt endpoint */, - .wMaxPacketSize = sizeof(struct st_tp_interrupt_t), - .bInterval = 1 /* ms */, -}; - -static void st_tp_interrupt_send(void) -{ - struct st_tp_interrupt_t report; - - memset(&report, 0, sizeof(report)); - - if (usb_buffer_index < spi_buffer_index) - report.flags |= ST_TP_INT_FRAME_AVAILABLE; - memcpy_to_usbram((void *)usb_sram_addr(st_tp_usb_int_buffer), - &report, sizeof(report)); - /* enable TX */ - STM32_TOGGLE_EP(USB_EP_ST_TOUCHPAD_INT, EP_TX_MASK, EP_TX_VALID, 0); - usb_wake(); -} - -static void st_tp_interrupt_tx(void) -{ - STM32_USB_EP(USB_EP_ST_TOUCHPAD_INT) &= EP_MASK; - - if (usb_buffer_index < spi_buffer_index) - /* pending frames */ - hook_call_deferred(&st_tp_interrupt_send_data, 0); -} - -static void st_tp_interrupt_event(enum usb_ep_event evt) -{ - int ep = USB_EP_ST_TOUCHPAD_INT; - - if (evt == USB_EVENT_RESET) { - btable_ep[ep].tx_addr = usb_sram_addr(st_tp_usb_int_buffer); - btable_ep[ep].tx_count = sizeof(struct st_tp_interrupt_t); - - STM32_USB_EP(ep) = ((ep << 0) | - EP_TX_VALID | - (3 << 9) /* interrupt EP */ | - EP_RX_DISAB); - } -} - -USB_DECLARE_EP(USB_EP_ST_TOUCHPAD_INT, st_tp_interrupt_tx, st_tp_interrupt_tx, - st_tp_interrupt_event); - -#endif - -/* Debugging commands */ -static int command_touchpad_st(int argc, char **argv) -{ - if (argc < 2) - return EC_ERROR_PARAM_COUNT; - if (strcasecmp(argv[1], "version") == 0) { - st_tp_read_system_info(1); - return EC_SUCCESS; - } else if (strcasecmp(argv[1], "calibrate") == 0) { - st_tp_panel_init(1); - return EC_SUCCESS; - } else if (strcasecmp(argv[1], "enable") == 0) { -#ifdef CONFIG_USB_ISOCHRONOUS - set_bits(&system_state, SYSTEM_STATE_DEBUG_MODE, - SYSTEM_STATE_DEBUG_MODE); - hook_call_deferred(&st_tp_enable_heat_map_data, 0); - return 0; -#else - return EC_ERROR_NOT_HANDLED; -#endif - } else if (strcasecmp(argv[1], "disable") == 0) { -#ifdef CONFIG_USB_ISOCHRONOUS - set_bits(&system_state, 0, SYSTEM_STATE_DEBUG_MODE); - hook_call_deferred(&st_tp_disable_heat_map_data, 0); - return 0; -#else - return EC_ERROR_NOT_HANDLED; -#endif - } else if (strcasecmp(argv[1], "dump") == 0) { - enable_deep_sleep(0); - dump_error(); - dump_memory(); - enable_deep_sleep(1); - return EC_SUCCESS; - } else if (strcasecmp(argv[1], "memory_dump") == 0) { - if (argc == 3 && !parse_bool(argv[2], &dump_memory_on_error)) - return EC_ERROR_PARAM2; - - ccprintf("memory_dump: %d\n", dump_memory_on_error); - return EC_SUCCESS; - } else { - return EC_ERROR_PARAM1; - } -} -DECLARE_CONSOLE_COMMAND(touchpad_st, command_touchpad_st, - "<enable | disable | version | calibrate | dump | " - "memory_dump <enable|disable>>", - "Read write spi. id is spi_devices array index"); diff --git a/driver/touchpad_st.h b/driver/touchpad_st.h deleted file mode 100644 index ecbddcb324..0000000000 --- a/driver/touchpad_st.h +++ /dev/null @@ -1,274 +0,0 @@ -/* Copyright 2018 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. - */ - -#ifndef __CROS_EC_TOUCHPAD_ST_H -#define __CROS_EC_TOUCHPAD_ST_H - -#include <stdint.h> - -#include "common.h" - -#define ST_VENDOR_ID 0x0483 - -#define ST_TP_DUMMY_BYTE 1 - -#define ST_TP_CMD_READ_ALL_EVENTS 0x87 -#define ST_TP_CMD_WRITE_SCAN_MODE_SELECT 0xA0 -#define ST_TP_CMD_WRITE_FEATURE_SELECT 0xA2 -#define ST_TP_CMD_WRITE_SYSTEM_COMMAND 0xA4 -#define ST_TP_CMD_WRITE_HOST_DATA_MEMORY 0xA6 -#define ST_TP_CMD_READ_HOST_DATA_MEMORY 0xA7 -#define ST_TP_CMD_WRITE_FW_CONFIG 0xA8 -#define ST_TP_CMD_READ_FW_CONFIG 0xA9 -#define ST_TP_CMD_SPI_HOST_BUFFER_ACK 0xC0 -#define ST_TP_CMD_READ_SPI_HOST_BUFFER 0xC1 - -#define ST_TP_CMD_WRITE_HW_REG 0xFA -#define ST_TP_CMD_READ_HW_REG 0xFB - -/* Max number of bytes that the DMA can burn on the flash in one shot in FTI */ -#define ST_TP_FLASH_BUFFER_SIZE (64 * 1024) -/* Max number of bytes that can be written in I2C to the DMA */ -#define ST_TP_DMA_CHUNK_SIZE 32 - -#define ST_HOST_BUFFER_DATA_VALID BIT(0) -#define ST_HOST_BUFFER_MT_READY BIT(3) -#define ST_HOST_BUFFER_SF_READY BIT(4) -#define ST_HOST_BUFFER_SS_READY BIT(5) - -#define ST_TP_SCAN_MODE_ACTIVE 0x00 -#define ST_TP_SCAN_MODE_LOW_POWER 0x01 -#define ST_TP_SCAN_MODE_TUNING_WIZARD 0x02 -#define ST_TP_SCAN_MODE_LOCKED 0x03 - -#define ST_TOUCH_ROWS (18) /* force len */ -#define ST_TOUCH_COLS (25) /* sense len */ - -#define ST_TOUCH_HEADER_SIZE 32 - -#define BYTES_PER_PIXEL 1 -/* Number of bits per pixel, this value is decided by experiments. */ -#define BITS_PER_PIXEL 8 - -#define ST_TOUCH_FRAME_SIZE (ST_TOUCH_ROWS * ST_TOUCH_COLS * \ - BYTES_PER_PIXEL) -#define ST_TOUCH_FORCE_SIZE (ST_TOUCH_ROWS * BYTES_PER_PIXEL) -#define ST_TOUCH_SENSE_SIZE (ST_TOUCH_COLS * BYTES_PER_PIXEL) - -#define ST_TP_MEM_ID_SYSTEM_INFO 0x01 - -#define ST_TP_FLASH_OFFSET_CODE (0x0000 << 2) -#define ST_TP_FLASH_OFFSET_PANEL_CFG (0x6800 << 2) -#define ST_TP_FLASH_OFFSET_CX (0x7000 << 2) -#define ST_TP_FLASH_OFFSET_CONFIG (0x7C00 << 2) - - -struct st_tp_host_data_header_t { -#define ST_TP_HEADER_MAGIC 0xA5 - uint8_t magic; /* this should always be ST_TP_HEADER_MAGIC */ - uint8_t host_data_mem_id; - uint16_t count; -} __packed; - -/* Compute offset of end of a member in given type */ -#define endof(type, member) (offsetof(type, member) + \ - sizeof(((type *)NULL)->member)) - -struct st_tp_system_info_t { - /* Part 1, basic info */ - struct st_tp_host_data_header_t header; - uint16_t api_ver_rev; - uint8_t api_ver_minor; - uint8_t api_ver_major; - uint16_t chip0_ver; - uint8_t chip0_id[2]; /* should be 0x3936 */ - uint16_t chip1_ver; - uint16_t chip1_id; - uint16_t fw_ver; - uint16_t svn_rev; - uint16_t cfg_ver; - uint16_t cfg_project_id; - uint16_t cx_ver; - uint16_t cx_project_id; - uint8_t cfg_afe_ver; - uint8_t cx_afe_ver; - uint8_t panel_cfg_afe_ver; - uint8_t protocol; - uint8_t die_id[16]; - uint64_t release_info; /* unsigned little endian 64 bit integer */ - uint32_t fw_crc; - uint32_t cfg_crc; -#define ST_TP_SYSTEM_INFO_PART_1_SIZE endof(struct st_tp_system_info_t, cfg_crc) -#define ST_TP_SYSTEM_INFO_PART_1_RESERVED 16 - - uint16_t scr_res_x; - uint16_t scr_res_y; - uint8_t scr_tx_len; - uint8_t scr_rx_len; - uint8_t key_len; - uint8_t frc_len; -#define ST_TP_SYSTEM_INFO_PART_2_SIZE (endof(struct st_tp_system_info_t, \ - frc_len) - \ - offsetof(struct st_tp_system_info_t, \ - scr_res_x)) -#define ST_TP_SYSTEM_INFO_PART_2_RESERVED 40 - -#if 0 /* the following parts are defined in spec, but not currently used. */ - - uint16_t dbg_frame_addr; -#define ST_TP_SYSTEM_INFO_PART_3_SIZE (endof(struct st_tp_system_info_t, \ - dbg_frame_addr) - \ - offsetof(struct st_tp_system_info_t, \ - dbg_frame_addr)) -#define ST_TP_SYSTEM_INFO_PART_3_RESERVED 6 - - uint16_t ms_scr_raw_addr; - uint16_t ms_scr_filter_addr; - uint16_t ms_scr_str_addr; - uint16_t ms_scr_bl_addr; - uint16_t ss_tch_tx_raw_addr; - uint16_t ss_tch_tx_filter_addr; - uint16_t ss_tch_tx_str_addr; - uint16_t ss_tch_tx_bl_addr; - uint16_t ss_tch_rx_raw_addr; - uint16_t ss_tch_rx_filter_addr; - uint16_t ss_tch_rx_str_addr; - uint16_t ss_tch_rx_bl_addr; - uint16_t key_raw_addr; - uint16_t key_filter_addr; - uint16_t key_str_addr; - uint16_t key_bl_addr; - uint16_t frc_raw_addr; - uint16_t frc_filter_addr; - uint16_t frc_str_addr; - uint16_t frc_bl_addr; - uint16_t ss_hvr_tx_raw_addr; - uint16_t ss_hvr_tx_filter_addr; - uint16_t ss_hvr_tx_str_addr; - uint16_t ss_hvr_tx_bl_addr; - uint16_t ss_hvr_rx_raw_addr; - uint16_t ss_hvr_rx_filter_addr; - uint16_t ss_hvr_rx_str_addr; - uint16_t ss_hvr_rx_bl_addr; - uint16_t ss_prx_tx_raw_addr; - uint16_t ss_prx_tx_filter_addr; - uint16_t ss_prx_tx_str_addr; - uint16_t ss_prx_tx_bl_addr; - uint16_t ss_prx_rx_raw_addr; - uint16_t ss_prx_rx_filter_addr; - uint16_t ss_prx_rx_str_addr; - uint16_t ss_prx_rx_bl_addr; -#define ST_TP_SYSTEM_INFO_PART_4_SIZE (endof(struct st_tp_system_info_t, \ - ss_prx_rx_bl_addr) - \ - offsetof(struct st_tp_system_info_t, \ - ms_scr_raw_addr)) -#endif /* if 0 */ -} __packed; - -#define ST_TP_SYSTEM_INFO_LEN (sizeof(struct st_tp_system_info_t) + \ - ST_TP_SYSTEM_INFO_PART_1_RESERVED) - -struct st_tp_host_buffer_header_t { -#define ST_TP_BUFFER_HEADER_DATA_VALID BIT(0) -#define ST_TP_BUFFER_HEADER_EVT_FIFO_NOT_EMPTY BIT(1) -#define ST_TP_BUFFER_HEADER_SYS_FAULT BIT(2) -#define ST_TP_BUFFER_HEADER_HEAT_MAP_MT_RDY BIT(3) -#define ST_TP_BUFFER_HEADER_HEAT_MAP_SF_RDY BIT(4) -#define ST_TP_BUFFER_HEADER_HEAT_MAP_SS_RDY BIT(5) -#define ST_TP_BUFFER_HEADER_DOMESWITCH_LVL BIT(6) - uint8_t flags; - uint8_t reserved[3]; - uint8_t heatmap_miss_count; - uint8_t event_count; - uint8_t event_miss_count; -} __packed; - -struct st_tp_host_buffer_heat_map_t { - uint8_t frame[ST_TOUCH_FRAME_SIZE]; -#if 0 /* we are not using these now */ - uint8_t force[ST_TOUCH_FORCE_SIZE]; - uint8_t sense[ST_TOUCH_SENSE_SIZE]; -#endif -} __packed; - -struct st_tp_event_t { -#define ST_TP_EVENT_MAGIC 0x3 - unsigned magic:2; /* should always be 0x3 */ - unsigned major_high:2; -#define ST_TP_EVENT_ID_CONTROLLER_READY 0x0 -#define ST_TP_EVENT_ID_ENTER_POINTER 0x1 -#define ST_TP_EVENT_ID_MOTION_POINTER 0x2 -#define ST_TP_EVENT_ID_LEAVE_POINTER 0x3 -#define ST_TP_EVENT_ID_STATUS_REPORT 0x4 -#define ST_TP_EVENT_ID_USER_REPORT 0x5 -#define ST_TP_EVENT_ID_DEBUG_REPORT 0xe -#define ST_TP_EVENT_ID_ERROR_REPORT 0xf - unsigned evt_id:4; - - union { - struct { -#define ST_TP_TOUCH_TYPE_INVALID 0x0 -#define ST_TP_TOUCH_TYPE_FINGER 0x1 -#define ST_TP_TOUCH_TYPE_GLOVE 0x2 -#define ST_TP_TOUCH_TYPE_STYLUS 0x3 -#define ST_TP_TOUCH_TYPE_PALM 0x4 - unsigned touch_type:4; - unsigned touch_id:4; - unsigned y:12; - unsigned x:12; - uint8_t z; - uint8_t minor:4; // need to be concat with minor_high - uint8_t major:4; // need to be concat with major_high - } __packed finger; - - struct { -#define ST_TP_STATUS_CMD_ECHO 0x1 -#define ST_TP_STATUS_FRAME_DROP 0x3 -#define ST_TP_STATUS_FCAL 0x5 -#define ST_TP_STATUS_BEACON 0x9 - uint8_t report_type; - uint8_t info[4]; - uint8_t reserved; - } __packed report; - } __packed ; /* anonymous */ - - unsigned minor_high:2; - unsigned reserved:1; - unsigned evt_left:5; -} __packed; - -struct st_tp_fw_header_t { - uint32_t signature; - uint32_t ftb_ver; - uint32_t chip_id; - uint32_t svn_ver; - uint32_t fw_ver; - uint32_t config_id; - uint32_t config_ver; - uint8_t reserved[8]; - uint64_t release_info; - uint32_t sec_size[4]; - uint32_t crc; -} __packed; - -enum ST_TP_MODE { - X_Y_MODE = 0, - HEAT_MAP_MODE, -}; - -#define ST_TP_DEBUG_CMD_RESET_TOUCHPAD 0x00 -#define ST_TP_DEBUG_CMD_CALIBRATE 0x01 -#define ST_TP_DEBUG_CMD_START_SCAN 0x02 -#define ST_TP_DEBUG_CMD_STOP_SCAN 0x03 -#define ST_TP_DEBUG_CMD_READ_BUF_HEADER 0x04 -#define ST_TP_DEBUG_CMD_READ_EVENTS 0x05 - -#define ST_TP_HEAT_MAP_THRESHOLD 10 - -/* A minimum version that supports heatmap mode. */ -#define ST_TP_MIN_HEATMAP_VERSION 0x12 - -#endif /* __CROS_EC_TOUCHPAD_ST_H */ - diff --git a/driver/usb_mux/amd_fp5.c b/driver/usb_mux/amd_fp5.c deleted file mode 100644 index a912d03365..0000000000 --- a/driver/usb_mux/amd_fp5.c +++ /dev/null @@ -1,119 +0,0 @@ -/* Copyright 2019 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. - * - * AMD FP5 USB/DP Mux. - */ - -#include "amd_fp5.h" -#include "chipset.h" -#include "common.h" -#include "i2c.h" -#include "usb_mux.h" - -static inline int amd_fp5_mux_read(int port, uint8_t *val) -{ - uint8_t buf[3] = { 0 }; - int rv; - - rv = i2c_xfer(I2C_PORT_USB_MUX, AMD_FP5_MUX_I2C_ADDR_FLAGS, - NULL, 0, buf, 3); - if (rv) - return rv; - - *val = buf[port + 1]; - - return EC_SUCCESS; -} - -static inline int amd_fp5_mux_write(int port, uint8_t val) -{ - return i2c_write8(I2C_PORT_USB_MUX, AMD_FP5_MUX_I2C_ADDR_FLAGS, - port, val); -} - -static int amd_fp5_init(int port) -{ - return EC_SUCCESS; -} - -static int amd_fp5_set_mux(int port, mux_state_t mux_state) -{ - uint8_t val = 0; - - /* - * This MUX is on the FP5 SoC. If that device is not powered then - * we either have to complain that it is not powered or if we were - * setting the state to OFF, then go ahead and report that we did - * it because a powered down MUX is off. - */ - if (chipset_in_state(CHIPSET_STATE_HARD_OFF)) - return (mux_state == TYPEC_MUX_NONE) - ? EC_SUCCESS - : EC_ERROR_NOT_POWERED; - - if ((mux_state & MUX_USB_ENABLED) && (mux_state & MUX_DP_ENABLED)) - val = (mux_state & MUX_POLARITY_INVERTED) - ? AMD_FP5_MUX_DOCK_INVERTED : AMD_FP5_MUX_DOCK; - else if (mux_state & MUX_USB_ENABLED) - val = (mux_state & MUX_POLARITY_INVERTED) - ? AMD_FP5_MUX_USB_INVERTED : AMD_FP5_MUX_USB; - else if (mux_state & MUX_DP_ENABLED) - val = (mux_state & MUX_POLARITY_INVERTED) - ? AMD_FP5_MUX_DP_INVERTED : AMD_FP5_MUX_DP; - - return amd_fp5_mux_write(port, val); -} - -static int amd_fp5_get_mux(int port, mux_state_t *mux_state) -{ - uint8_t val = AMD_FP5_MUX_SAFE; - - /* - * This MUX is on the FP5 SoC. Only access the device if we - * have power. If that device is not powered then claim the - * state to be NONE, which is SAFE. - */ - if (!chipset_in_state(CHIPSET_STATE_HARD_OFF)) { - int rv; - - rv = amd_fp5_mux_read(port, &val); - if (rv) - return rv; - } - - - switch (val) { - case AMD_FP5_MUX_USB: - *mux_state = MUX_USB_ENABLED; - break; - case AMD_FP5_MUX_USB_INVERTED: - *mux_state = MUX_USB_ENABLED | MUX_POLARITY_INVERTED; - break; - case AMD_FP5_MUX_DOCK: - *mux_state = MUX_USB_ENABLED | MUX_DP_ENABLED; - break; - case AMD_FP5_MUX_DOCK_INVERTED: - *mux_state = MUX_USB_ENABLED | MUX_DP_ENABLED - | MUX_POLARITY_INVERTED; - break; - case AMD_FP5_MUX_DP: - *mux_state = MUX_DP_ENABLED; - break; - case AMD_FP5_MUX_DP_INVERTED: - *mux_state = MUX_DP_ENABLED | MUX_POLARITY_INVERTED; - break; - case AMD_FP5_MUX_SAFE: - default: - *mux_state = TYPEC_MUX_NONE; - break; - } - - return EC_SUCCESS; -} - -const struct usb_mux_driver amd_fp5_usb_mux_driver = { - .init = amd_fp5_init, - .set = amd_fp5_set_mux, - .get = amd_fp5_get_mux, -}; diff --git a/driver/usb_mux/amd_fp5.h b/driver/usb_mux/amd_fp5.h deleted file mode 100644 index 7534ea0d8a..0000000000 --- a/driver/usb_mux/amd_fp5.h +++ /dev/null @@ -1,21 +0,0 @@ -/* Copyright 2019 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. - * - * AMD FP5 USB/DP Mux. - */ - -#ifndef __CROS_EC_USB_MUX_AMD_FP5_H -#define __CROS_EC_USB_MUX_AMD_FP5_H - -#define AMD_FP5_MUX_I2C_ADDR_FLAGS 0x5C - -#define AMD_FP5_MUX_SAFE 0x00 -#define AMD_FP5_MUX_USB 0x02 -#define AMD_FP5_MUX_USB_INVERTED 0x11 -#define AMD_FP5_MUX_DOCK 0x06 -#define AMD_FP5_MUX_DOCK_INVERTED 0x19 -#define AMD_FP5_MUX_DP 0x0C -#define AMD_FP5_MUX_DP_INVERTED 0x1C - -#endif /* __CROS_EC_USB_MUX_AMD_FP5_H */ diff --git a/driver/usb_mux/it5205.c b/driver/usb_mux/it5205.c deleted file mode 100644 index 9a6f71dade..0000000000 --- a/driver/usb_mux/it5205.c +++ /dev/null @@ -1,135 +0,0 @@ -/* Copyright 2017 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. - * - * ITE IT5205 Type-C USB alternate mode mux. - */ - -#include "common.h" -#include "console.h" -#include "i2c.h" -#include "it5205.h" -#include "usb_mux.h" -#include "util.h" - -#define MUX_STATE_DP_USB_MASK (MUX_USB_ENABLED | MUX_DP_ENABLED) - -static int it5205_read(int port, uint8_t reg, int *val) -{ - return i2c_read8(I2C_PORT_USB_MUX, MUX_ADDR(port), reg, val); -} - -static int it5205_write(int port, uint8_t reg, uint8_t val) -{ - return i2c_write8(I2C_PORT_USB_MUX, MUX_ADDR(port), reg, val); -} - -struct mux_chip_id_t { - uint8_t chip_id; - uint8_t reg; -}; - -static const struct mux_chip_id_t mux_chip_id_verify[] = { - { '5', IT5205_REG_CHIP_ID3}, - { '2', IT5205_REG_CHIP_ID2}, - { '0', IT5205_REG_CHIP_ID1}, - { '5', IT5205_REG_CHIP_ID0}, -}; - -static int it5205_init(int port) -{ - int i, val, ret; - - /* bit[0]: mux power on, bit[7-1]: reserved. */ - ret = it5205_write(port, IT5205_REG_MUXPDR, 0); - if (ret) - return ret; - /* Verify chip ID registers. */ - for (i = 0; i < ARRAY_SIZE(mux_chip_id_verify); i++) { - ret = it5205_read(port, mux_chip_id_verify[i].reg, &val); - if (ret) - return ret; - - if (val != mux_chip_id_verify[i].chip_id) - return EC_ERROR_UNKNOWN; - } - - return EC_SUCCESS; -} - -/* Writes control register to set switch mode */ -static int it5205_set_mux(int port, mux_state_t mux_state) -{ - uint8_t reg; - - switch (mux_state & MUX_STATE_DP_USB_MASK) { - case MUX_USB_ENABLED: - reg = IT5205_USB; - break; - case MUX_DP_ENABLED: - reg = IT5205_DP; - break; - case MUX_STATE_DP_USB_MASK: - reg = IT5205_DP_USB; - break; - default: - reg = 0; - break; - } - - if (mux_state & MUX_POLARITY_INVERTED) - reg |= IT5205_POLARITY_INVERTED; - - return it5205_write(port, IT5205_REG_MUXCR, reg); -} - -/* Reads control register and updates mux_state accordingly */ -static int it5205_get_mux(int port, mux_state_t *mux_state) -{ - int reg, ret; - - ret = it5205_read(port, IT5205_REG_MUXCR, ®); - if (ret) - return ret; - - switch (reg & IT5205_DP_USB_CTRL_MASK) { - case IT5205_USB: - *mux_state = MUX_USB_ENABLED; - break; - case IT5205_DP: - *mux_state = MUX_DP_ENABLED; - break; - case IT5205_DP_USB: - *mux_state = MUX_STATE_DP_USB_MASK; - break; - default: - *mux_state = 0; - break; - } - - if (reg & IT5205_POLARITY_INVERTED) - *mux_state |= MUX_POLARITY_INVERTED; - - return EC_SUCCESS; -} - -static int it5205_enter_low_power_mode(int port) -{ - int rv; - - /* Turn off all switches */ - rv = it5205_write(port, IT5205_REG_MUXCR, 0); - - if (rv) - return rv; - - /* Power down mux */ - return it5205_write(port, IT5205_REG_MUXPDR, IT5205_MUX_POWER_DOWN); -} - -const struct usb_mux_driver it5205_usb_mux_driver = { - .init = &it5205_init, - .set = &it5205_set_mux, - .get = &it5205_get_mux, - .enter_low_power_mode = &it5205_enter_low_power_mode, -}; diff --git a/driver/usb_mux/it5205.h b/driver/usb_mux/it5205.h deleted file mode 100644 index 9e9c4ccfcc..0000000000 --- a/driver/usb_mux/it5205.h +++ /dev/null @@ -1,34 +0,0 @@ -/* Copyright 2017 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. - * - * ITE IT5205 Type-C USB alternate mode mux. - */ - -#ifndef __CROS_EC_IT5205_H -#define __CROS_EC_IT5205_H - -/* I2C interface */ -#define IT5205_I2C_ADDR1_FLAGS 0x48 -#define IT5205_I2C_ADDR2_FLAGS 0x58 - -/* Chip ID registers */ -#define IT5205_REG_CHIP_ID3 0x4 -#define IT5205_REG_CHIP_ID2 0x5 -#define IT5205_REG_CHIP_ID1 0x6 -#define IT5205_REG_CHIP_ID0 0x7 - -/* MUX power down register */ -#define IT5205_REG_MUXPDR 0x10 -#define IT5205_MUX_POWER_DOWN BIT(0) - -/* MUX control register */ -#define IT5205_REG_MUXCR 0x11 -#define IT5205_POLARITY_INVERTED BIT(4) - -#define IT5205_DP_USB_CTRL_MASK 0x0f -#define IT5205_DP 0x0f -#define IT5205_DP_USB 0x03 -#define IT5205_USB 0x07 - -#endif /* __CROS_EC_IT5205_H */ diff --git a/driver/usb_mux/pi3usb30532.c b/driver/usb_mux/pi3usb30532.c deleted file mode 100644 index e5af1b90a6..0000000000 --- a/driver/usb_mux/pi3usb30532.c +++ /dev/null @@ -1,112 +0,0 @@ -/* 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. - * - * Pericom PI3USB30532 USB port switch driver. - */ - -#include "common.h" -#include "i2c.h" -#include "pi3usb30532.h" -#include "usb_mux.h" -#include "util.h" - -static int pi3usb30532_read(int port, uint8_t reg, uint8_t *val) -{ - int read, res; - - /* - * First byte read will be slave address (ignored). - * Second byte read will be vendor ID. - * Third byte read will be selection control. - */ - res = i2c_read16(I2C_PORT_USB_MUX, MUX_ADDR(port), - 0, &read); - if (res) - return res; - - if (reg == PI3USB30532_REG_VENDOR) - *val = read & 0xff; - else /* reg == PI3USB30532_REG_CONTROL */ - *val = (read >> 8) & 0xff; - - return EC_SUCCESS; -} - -static int pi3usb30532_write(int port, uint8_t reg, uint8_t val) -{ - if (reg != PI3USB30532_REG_CONTROL) - return EC_ERROR_UNKNOWN; - - return i2c_write8(I2C_PORT_USB_MUX, MUX_ADDR(port), - 0, val); -} - -static int pi3usb30532_reset(int port) -{ - return pi3usb30532_write( - port, - PI3USB30532_REG_CONTROL, - (PI3USB30532_MODE_POWERDOWN & PI3USB30532_CTRL_MASK) | - PI3USB30532_CTRL_RSVD); -} - -static int pi3usb30532_init(int port) -{ - uint8_t val; - int res; - - res = pi3usb30532_reset(port); - if (res) - return res; - res = pi3usb30532_read(port, PI3USB30532_REG_VENDOR, &val); - if (res) - return res; - if (val != PI3USB30532_VENDOR_ID) - return EC_ERROR_UNKNOWN; - - return EC_SUCCESS; -} - -/* Writes control register to set switch mode */ -static int pi3usb30532_set_mux(int port, mux_state_t mux_state) -{ - uint8_t reg = 0; - - if (mux_state & MUX_USB_ENABLED) - reg |= PI3USB30532_MODE_USB; - if (mux_state & MUX_DP_ENABLED) - reg |= PI3USB30532_MODE_DP; - if (mux_state & MUX_POLARITY_INVERTED) - reg |= PI3USB30532_BIT_SWAP; - - return pi3usb30532_write(port, PI3USB30532_REG_CONTROL, - reg | PI3USB30532_CTRL_RSVD); -} - -/* Reads control register and updates mux_state accordingly */ -static int pi3usb30532_get_mux(int port, mux_state_t *mux_state) -{ - uint8_t reg = 0; - uint8_t res; - - *mux_state = 0; - res = pi3usb30532_read(port, PI3USB30532_REG_CONTROL, ®); - if (res) - return res; - - if (reg & PI3USB30532_MODE_USB) - *mux_state |= MUX_USB_ENABLED; - if (reg & PI3USB30532_MODE_DP) - *mux_state |= MUX_DP_ENABLED; - if (reg & PI3USB30532_BIT_SWAP) - *mux_state |= MUX_POLARITY_INVERTED; - - return EC_SUCCESS; -} - -const struct usb_mux_driver pi3usb30532_usb_mux_driver = { - .init = pi3usb30532_init, - .set = pi3usb30532_set_mux, - .get = pi3usb30532_get_mux, -}; diff --git a/driver/usb_mux/pi3usb30532.h b/driver/usb_mux/pi3usb30532.h deleted file mode 100644 index 7f120a9f85..0000000000 --- a/driver/usb_mux/pi3usb30532.h +++ /dev/null @@ -1,65 +0,0 @@ -/* 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. - * - * Pericom PI3USB30532 USB port switch driver. - */ - -#ifndef __CROS_EC_PI3USB30532_H -#define __CROS_EC_PI3USB30532_H - -#include "usb_pd.h" - -/* USB switch registers */ -#define PI3USB30532_REG_ADDR 0x00 -#define PI3USB30532_REG_VENDOR 0x01 -#define PI3USB30532_REG_CONTROL 0x02 -/* Control register field */ -#define PI3USB30532_CTRL_MASK 0x7 -#define PI3USB30532_CTRL_RSVD 0 -/* Switch vendor ID */ -#define PI3USB30532_VENDOR_ID 0 - -/* PI3USB30532 control flags */ -#define PI3USB30532_BIT_SWAP BIT(0) -#define PI3USB30532_BIT_DP BIT(1) -#define PI3USB30532_BIT_USB BIT(2) - -/* PI3USB30532 modes */ -/* Power down, switch open */ -#define PI3USB30532_MODE_POWERDOWN 0 -/* Keep power on, switch open */ -#define PI3USB30532_MODE_POWERON 1 -/* 4-lane DP 1.2 - * dp0~3 : rx2, tx2, tx1, rx1 - * hpd+/-: rfu1, rfu2 - */ -#define PI3USB30532_MODE_DP PI3USB30532_BIT_DP -/* 4-lane DP 1.2 swap - * dp0~3 : rx1, tx1, tx2, rx2 - * hpd+/-: rfu2, rfu1 - */ -#define PI3USB30532_MODE_DP_SWAP (PI3USB30532_MODE_DP | PI3USB30532_BIT_SWAP) -/* USB3 - * tx/rx : tx1, rx1 - */ -#define PI3USB30532_MODE_USB PI3USB30532_BIT_USB -/* USB3 swap - * tx/rx : tx2, rx2 - */ -#define PI3USB30532_MODE_USB_SWAP (PI3USB30532_MODE_USB | PI3USB30532_BIT_SWAP) -/* 2-lane DP 1.2 + USB3 - * tx/rx : tx1, rx1 - * dp0~1 : rx2, tx2 - * hpd+/-: rfu1, rfu2 - */ -#define PI3USB30532_MODE_DP_USB (PI3USB30532_BIT_DP | PI3USB30532_BIT_USB) -/* 2-lane DP 1.2 + USB3, swap - * tx/rx : tx2, rx2 - * dp0-1 : rx1, tx1 - * hpd+/-: rfu2, rfu1 - */ -#define PI3USB30532_MODE_DP_USB_SWAP (PI3USB30532_MODE_DP_USB | \ - PI3USB30532_BIT_SWAP) - -#endif /* __CROS_EC_PI3USB30532_H */ diff --git a/driver/usb_mux/pi3usb9281.h b/driver/usb_mux/pi3usb9281.h deleted file mode 100644 index 69b671500e..0000000000 --- a/driver/usb_mux/pi3usb9281.h +++ /dev/null @@ -1,82 +0,0 @@ -/* Copyright 2014 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. - * - * Pericom PI3USB9281 USB port switch. - */ - -#ifndef __CROS_EC_PI3USB9281_H -#define __CROS_EC_PI3USB9281_H - -#define PI3USB9281_REG_DEV_ID 0x01 -#define PI3USB9281_REG_CONTROL 0x02 -#define PI3USB9281_REG_INT 0x03 -#define PI3USB9281_REG_INT_MASK 0x05 -#define PI3USB9281_REG_DEV_TYPE 0x0a -#define PI3USB9281_REG_CHG_STATUS 0x0e -#define PI3USB9281_REG_MANUAL 0x13 -#define PI3USB9281_REG_RESET 0x1b -#define PI3USB9281_REG_VBUS 0x1d - -#define PI3USB9281_DEV_ID 0x10 -#define PI3USB9281_DEV_ID_A 0x18 - -#define PI3USB9281_CTRL_INT_DIS BIT(0) -#define PI3USB9281_CTRL_AUTO BIT(2) -#define PI3USB9281_CTRL_SWITCH_AUTO BIT(4) -/* Bits 5 thru 7 are read X, write 0 */ -#define PI3USB9281_CTRL_MASK 0x1f -/* Bits 1 and 3 are read 1, write 1 */ -#define PI3USB9281_CTRL_RSVD_1 0x0a - -#define PI3USB9281_PIN_MANUAL_VBUS (3 << 0) -#define PI3USB9281_PIN_MANUAL_DP BIT(2) -#define PI3USB9281_PIN_MANUAL_DM BIT(5) - -#define PI3USB9281_INT_ATTACH BIT(0) -#define PI3USB9281_INT_DETACH BIT(1) -#define PI3USB9281_INT_OVP BIT(5) -#define PI3USB9281_INT_OCP BIT(6) -#define PI3USB9281_INT_OVP_OC BIT(7) -#define PI3USB9281_INT_ATTACH_DETACH (PI3USB9281_INT_ATTACH | \ - PI3USB9281_INT_DETACH) - -#define PI3USB9281_TYPE_NONE 0 -#define PI3USB9281_TYPE_MHL BIT(0) -#define PI3USB9281_TYPE_OTG BIT(1) -#define PI3USB9281_TYPE_SDP BIT(2) -#define PI3USB9281_TYPE_CAR BIT(4) -#define PI3USB9281_TYPE_CDP BIT(5) -#define PI3USB9281_TYPE_DCP BIT(6) - -#define PI3USB9281_CHG_NONE 0 -#define PI3USB9281_CHG_CAR_TYPE1 BIT(1) -#define PI3USB9281_CHG_CAR_TYPE2 (3 << 0) -#define PI3USB9281_CHG_APPLE_1A BIT(2) -#define PI3USB9281_CHG_APPLE_2A BIT(3) -#define PI3USB9281_CHG_APPLE_2_4A BIT(4) -/* Check if charge status has any connection */ -#define PI3USB9281_CHG_STATUS_ANY(x) (((x) & 0x1f) > 1) - -/* Define configuration of one pi3usb9281 part */ -struct pi3usb9281_config { - /* i2c port that chip resides on */ - int i2c_port; - /* GPIO for chip selection in muxed configuration */ - enum gpio_signal mux_gpio; - /* Logic level of mux_gpio to select chip */ - int mux_gpio_level; - /* Mutex to lock access to mux gpio or NULL if no mux exists */ - struct mutex *mux_lock; -}; - -/* Configuration struct defined at board level */ -extern struct pi3usb9281_config pi3usb9281_chips[]; - -/* Enable interrupts. */ -int pi3usb9281_enable_interrupts(int port); - -/* Get the device type */ -int pi3usb9281_get_device_type(int port); - -#endif /* __CROS_EC_PI3USB9281_H */ diff --git a/driver/usb_mux/ps874x.c b/driver/usb_mux/ps874x.c deleted file mode 100644 index db13180c1c..0000000000 --- a/driver/usb_mux/ps874x.c +++ /dev/null @@ -1,127 +0,0 @@ -/* Copyright 2017 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. - * - * Parade PS874X USB Type-C Redriving Switch for USB Host / DisplayPort. - */ - -#include "common.h" -#include "i2c.h" -#include "ps874x.h" -#include "usb_mux.h" -#include "util.h" - -static inline int ps874x_read(int port, uint8_t reg, int *val) -{ - return i2c_read8(I2C_PORT_USB_MUX, MUX_ADDR(port), - reg, val); -} - -static inline int ps874x_write(int port, uint8_t reg, uint8_t val) -{ - return i2c_write8(I2C_PORT_USB_MUX, MUX_ADDR(port), - reg, val); -} - -static int ps874x_init(int port) -{ - int val; - int res; - - /* Reset chip back to power-on state */ - res = ps874x_write(port, PS874X_REG_MODE, PS874X_MODE_POWER_DOWN); - if (res) - return res; - - /* - * Verify revision / chip ID registers. - */ - res = ps874x_read(port, PS874X_REG_REVISION_ID1, &val); - if (res) - return res; - -#ifdef CONFIG_USB_MUX_PS8743 - /* - * From Parade: PS8743 may have REVISION_ID1 as 0 or 1 - * Rev 1 is derived from Rev 0 and have same functionality. - */ - if (val != PS874X_REVISION_ID1_0 && val != PS874X_REVISION_ID1_1) - return EC_ERROR_UNKNOWN; -#else - if (val != PS874X_REVISION_ID1) - return EC_ERROR_UNKNOWN; -#endif - - res = ps874x_read(port, PS874X_REG_REVISION_ID2, &val); - if (res) - return res; - if (val != PS874X_REVISION_ID2) - return EC_ERROR_UNKNOWN; - - res = ps874x_read(port, PS874X_REG_CHIP_ID1, &val); - if (res) - return res; - if (val != PS874X_CHIP_ID1) - return EC_ERROR_UNKNOWN; - - res = ps874x_read(port, PS874X_REG_CHIP_ID2, &val); - if (res) - return res; - if (val != PS874X_CHIP_ID2) - return EC_ERROR_UNKNOWN; - - return EC_SUCCESS; -} - -/* Writes control register to set switch mode */ -static int ps874x_set_mux(int port, mux_state_t mux_state) -{ - uint8_t reg = 0; - - if (mux_state & MUX_USB_ENABLED) - reg |= PS874X_MODE_USB_ENABLED; - if (mux_state & MUX_DP_ENABLED) - reg |= PS874X_MODE_DP_ENABLED; - if (mux_state & MUX_POLARITY_INVERTED) - reg |= PS874X_MODE_POLARITY_INVERTED; - - return ps874x_write(port, PS874X_REG_MODE, reg); -} - -/* Reads control register and updates mux_state accordingly */ -static int ps874x_get_mux(int port, mux_state_t *mux_state) -{ - int reg; - int res; - - res = ps874x_read(port, PS874X_REG_STATUS, ®); - if (res) - return res; - - *mux_state = 0; - if (reg & PS874X_STATUS_USB_ENABLED) - *mux_state |= MUX_USB_ENABLED; - if (reg & PS874X_STATUS_DP_ENABLED) - *mux_state |= MUX_DP_ENABLED; - if (reg & PS874X_STATUS_POLARITY_INVERTED) - *mux_state |= MUX_POLARITY_INVERTED; - - return EC_SUCCESS; -} - -/* Tune USB Tx/Rx Equalization */ -int ps874x_tune_usb_eq(int port, uint8_t tx, uint8_t rx) -{ - int ret; - - ret = ps874x_write(port, PS874X_REG_USB_EQ_TX, tx); - ret |= ps874x_write(port, PS874X_REG_USB_EQ_RX, rx); - - return ret; -} - -const struct usb_mux_driver ps874x_usb_mux_driver = { - .init = ps874x_init, - .set = ps874x_set_mux, - .get = ps874x_get_mux, -}; diff --git a/driver/usb_mux/ps874x.h b/driver/usb_mux/ps874x.h deleted file mode 100644 index e7bd185bcf..0000000000 --- a/driver/usb_mux/ps874x.h +++ /dev/null @@ -1,114 +0,0 @@ -/* Copyright 2017 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. - * - * Parade PS874X USB Type-C Redriving Switch for USB Host / DisplayPort. - */ - -#ifndef __CROS_EC_PS874X_H -#define __CROS_EC_PS874X_H - -/* Mode register for setting mux */ -#define PS874X_REG_MODE 0x00 -#ifdef CONFIG_USB_MUX_PS8740 - #define PS874X_MODE_POLARITY_INVERTED BIT(4) - #define PS874X_MODE_USB_ENABLED BIT(5) - #define PS874X_MODE_DP_ENABLED BIT(6) - #define PS874X_MODE_POWER_DOWN BIT(7) -#elif defined(CONFIG_USB_MUX_PS8743) - #define PS874X_MODE_POLARITY_INVERTED BIT(2) - #define PS874X_MODE_FLIP_PIN_ENABLED BIT(3) - #define PS874X_MODE_USB_ENABLED BIT(4) - #define PS874X_MODE_CE_USB_ENABLED BIT(5) - #define PS874X_MODE_DP_ENABLED BIT(6) - #define PS874X_MODE_CE_DP_ENABLED BIT(7) - /* To reset the state machine to default */ - #define PS874X_MODE_POWER_DOWN (PS874X_MODE_CE_USB_ENABLED | \ - PS874X_MODE_CE_DP_ENABLED) -#endif - -/* Status register for checking mux state */ -#define PS874X_REG_STATUS 0x09 -#define PS874X_STATUS_POLARITY_INVERTED BIT(2) -#define PS874X_STATUS_USB_ENABLED BIT(3) -#define PS874X_STATUS_DP_ENABLED BIT(4) -#define PS874X_STATUS_HPD_ASSERTED BIT(7) - -/* Chip ID / revision registers and expected fused values */ -#define PS874X_REG_REVISION_ID1 0xf0 -#define PS874X_REG_REVISION_ID2 0xf1 -#define PS874X_REG_CHIP_ID1 0xf2 -#define PS874X_REG_CHIP_ID2 0xf3 -#ifdef CONFIG_USB_MUX_PS8740 - #define PS874X_REVISION_ID1 0x00 - #define PS874X_REVISION_ID2 0x0a - #define PS874X_CHIP_ID1 0x40 -#elif defined(CONFIG_USB_MUX_PS8743) - #define PS874X_REVISION_ID1_0 0x00 - #define PS874X_REVISION_ID1_1 0x01 - #define PS874X_REVISION_ID2 0x0b - #define PS874X_CHIP_ID1 0x41 -#endif -#define PS874X_CHIP_ID2 0x87 - -/* USB equalization settings for Host to Mux */ -#define PS874X_REG_USB_EQ_TX 0x32 -#ifdef CONFIG_USB_MUX_PS8740 - #define PS874X_USB_EQ_TX_10_1_DB 0x00 - #define PS874X_USB_EQ_TX_14_3_DB 0x20 - #define PS874X_USB_EQ_TX_8_5_DB 0x40 - #define PS874X_USB_EQ_TX_6_5_DB 0x60 - #define PS874X_USB_EQ_TX_11_5_DB 0x80 - #define PS874X_USB_EQ_TX_9_5_DB 0xc0 - #define PS874X_USB_EQ_TX_7_5_DB 0xe0 - #define PS874X_USB_EQ_TERM_100_OHM (0 << 2) - #define PS874X_USB_EQ_TERM_85_OHM BIT(2) -#elif defined(CONFIG_USB_MUX_PS8743) - #define PS874X_USB_EQ_TX_12_8_DB 0x00 - #define PS874X_USB_EQ_TX_17_DB 0x20 - #define PS874X_USB_EQ_TX_7_7_DB 0x40 - #define PS874X_USB_EQ_TX_3_6_DB 0x60 - #define PS874X_USB_EQ_TX_15_DB 0x80 - #define PS874X_USB_EQ_TX_10_9_DB 0xc0 - #define PS874X_USB_EQ_TX_4_5_DB 0xe0 -#endif - -/* USB equalization settings for Connector to Mux */ -#define PS874X_REG_USB_EQ_RX 0x3b -#ifdef CONFIG_USB_MUX_PS8740 - #define PS874X_USB_EQ_RX_4_4_DB 0x00 - #define PS874X_USB_EQ_RX_7_0_DB 0x10 - #define PS874X_USB_EQ_RX_8_2_DB 0x20 - #define PS874X_USB_EQ_RX_9_4_DB 0x30 - #define PS874X_USB_EQ_RX_10_2_DB 0x40 - #define PS874X_USB_EQ_RX_11_4_DB 0x50 - #define PS874X_USB_EQ_RX_14_3_DB 0x60 - #define PS874X_USB_EQ_RX_14_8_DB 0x70 - #define PS874X_USB_EQ_RX_15_2_DB 0x80 - #define PS874X_USB_EQ_RX_15_5_DB 0x90 - #define PS874X_USB_EQ_RX_16_2_DB 0xa0 - #define PS874X_USB_EQ_RX_17_3_DB 0xb0 - #define PS874X_USB_EQ_RX_18_4_DB 0xc0 - #define PS874X_USB_EQ_RX_20_1_DB 0xd0 - #define PS874X_USB_EQ_RX_21_3_DB 0xe0 -#elif defined(CONFIG_USB_MUX_PS8743) - #define PS874X_USB_EQ_RX_2_4_DB 0x00 - #define PS874X_USB_EQ_RX_5_DB 0x10 - #define PS874X_USB_EQ_RX_6_5_DB 0x20 - #define PS874X_USB_EQ_RX_7_4_DB 0x30 - #define PS874X_USB_EQ_RX_8_7_DB 0x40 - #define PS874X_USB_EQ_RX_10_9_DB 0x50 - #define PS874X_USB_EQ_RX_12_8_DB 0x60 - #define PS874X_USB_EQ_RX_13_8_DB 0x70 - #define PS874X_USB_EQ_RX_14_8_DB 0x80 - #define PS874X_USB_EQ_RX_15_4_DB 0x90 - #define PS874X_USB_EQ_RX_16_0_DB 0xa0 - #define PS874X_USB_EQ_RX_16_7_DB 0xb0 - #define PS874X_USB_EQ_RX_18_8_DB 0xc0 - #define PS874X_USB_EQ_RX_21_3_DB 0xd0 - #define PS874X_USB_EQ_RX_22_2_DB 0xe0 -#endif - -int ps874x_tune_usb_eq(int i2c_addr, uint8_t tx, uint8_t rx); - -#endif /* __CROS_EC_PS874X_H */ diff --git a/driver/usb_mux/usb_mux.c b/driver/usb_mux/usb_mux.c deleted file mode 100644 index 93c741c1e9..0000000000 --- a/driver/usb_mux/usb_mux.c +++ /dev/null @@ -1,292 +0,0 @@ -/* 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. - */ - -/* USB mux high-level driver. */ - -#include "common.h" -#include "console.h" -#include "host_command.h" -#include "usb_mux.h" -#include "usbc_ppc.h" -#include "util.h" - -#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args) - -static int enable_debug_prints; - -/* - * Flags will reset to 0 after sysjump; This works for current flags as LPM will - * get reset in the init method which is called during PD task startup. - */ -static uint8_t flags[CONFIG_USB_PD_PORT_MAX_COUNT]; - -#define USB_MUX_FLAG_IN_LPM BIT(0) /* Device is in low power mode. */ - - -static void enter_low_power_mode(int port) -{ - const struct usb_mux *mux = &usb_muxes[port]; - int res; - - /* - * Set LPM flag regardless of method presence or method failure. We want - * know know that we tried to put the device in low power mode so we can - * re-initialize the device on the next access. - */ - flags[port] |= USB_MUX_FLAG_IN_LPM; - - /* Apply any low power customization if present */ - if (mux->driver->enter_low_power_mode) { - res = mux->driver->enter_low_power_mode(port); - if (res) { - CPRINTS("Err: %s mux port(%d): %d", - __func__, port, res); - return; - } - } - - if (IS_ENABLED(CONFIG_USBC_MUX_RETIMER)) { - const struct usb_retimer *retimer = &usb_retimers[port]; - - if (retimer->driver && retimer->driver->enter_low_power_mode) { - res = retimer->driver->enter_low_power_mode(port); - if (res) { - CPRINTS("Err: %s retimer port(%d): %d", - __func__, port, res); - return; - } - } - } -} - -static inline void exit_low_power_mode(int port) -{ - /* If we are in low power, initialize device (which clears LPM flag) */ - if (flags[port] & USB_MUX_FLAG_IN_LPM) - usb_mux_init(port); -} - -void usb_mux_init(int port) -{ - const struct usb_mux *mux = &usb_muxes[port]; - int res; - - ASSERT(port >= 0 && port < CONFIG_USB_PD_PORT_MAX_COUNT); - - res = mux->driver->init(port); - if (res) { - CPRINTS("Err: init mux port(%d): %d", port, res); - return; - } - - if (IS_ENABLED(CONFIG_USBC_MUX_RETIMER)) { - const struct usb_retimer *retimer = &usb_retimers[port]; - - if (retimer->driver && retimer->driver->init) { - res = retimer->driver->init(port); - if (res) { - CPRINTS("Err: init retimer port(%d): %d", - port, res); - return; - } - } - } - - /* Device is always out of LPM after initialization. */ - flags[port] &= ~USB_MUX_FLAG_IN_LPM; - - /* Apply board specific initialization */ - if (mux->board_init) { - res = mux->board_init(port); - - if (res) - CPRINTS("Err: board_init mux port(%d): %d", port, res); - } -} - -/* - * TODO(crbug.com/505480): Setting muxes often involves I2C transcations, - * which can block. Consider implementing an asynchronous task. - */ -void usb_mux_set(int port, enum typec_mux mux_mode, - enum usb_switch usb_mode, int polarity) -{ - const struct usb_mux *mux = &usb_muxes[port]; - int res; - mux_state_t mux_state; - const int should_enter_low_power_mode = - mux_mode == TYPEC_MUX_NONE && usb_mode == USB_SWITCH_DISCONNECT; - - /* Configure USB2.0 */ - if (IS_ENABLED(CONFIG_USB_CHARGER)) - usb_charger_set_switches(port, usb_mode); - - /* - * Don't wake device up just to put it back to sleep. Low power mode - * flag is only set if the mux set() operation succeeded previously for - * the same disconnected state. - */ - if (should_enter_low_power_mode && (flags[port] & USB_MUX_FLAG_IN_LPM)) - return; - - exit_low_power_mode(port); - - /* Configure superspeed lanes */ - mux_state = ((mux_mode != TYPEC_MUX_NONE) && polarity) - ? mux_mode | MUX_POLARITY_INVERTED - : mux_mode; - - res = mux->driver->set(port, mux_state); - if (res) { - CPRINTS("Err: set mux port(%d): %d", port, res); - return; - } - - if (IS_ENABLED(CONFIG_USBC_MUX_RETIMER)) { - const struct usb_retimer *retimer = &usb_retimers[port]; - - if (retimer->driver && retimer->driver->set) { - res = retimer->driver->set(port, mux_state); - if (res) { - CPRINTS("Err: set retimer port(%d): %d", - port, res); - return; - } - } - } - - if (enable_debug_prints) - CPRINTS( - "usb/dp mux: port(%d) typec_mux(%d) usb2(%d) polarity(%d)", - port, mux_mode, usb_mode, polarity); - - /* - * If we are completely disconnecting the mux, then we should put it in - * its lowest power state. - */ - if (should_enter_low_power_mode) - enter_low_power_mode(port); -} - -mux_state_t usb_mux_get(int port) -{ - const struct usb_mux *mux = &usb_muxes[port]; - int res; - mux_state_t mux_state; - - exit_low_power_mode(port); - - res = mux->driver->get(port, &mux_state); - if (res) { - CPRINTS("Err: get mux port(%d): %d", port, res); - return 0; - } - - return mux_state; -} - -void usb_mux_flip(int port) -{ - const struct usb_mux *mux = &usb_muxes[port]; - int res; - mux_state_t mux_state; - - exit_low_power_mode(port); - - res = mux->driver->get(port, &mux_state); - if (res) { - CPRINTS("Err: get mux port(%d): %d", port, res); - return; - } - - if (mux_state & MUX_POLARITY_INVERTED) - mux_state &= ~MUX_POLARITY_INVERTED; - else - mux_state |= MUX_POLARITY_INVERTED; - - res = mux->driver->set(port, mux_state); - if (res) - CPRINTS("Err: set mux port(%d): %d", port, res); -} - -#ifdef CONFIG_CMD_TYPEC -static int command_typec(int argc, char **argv) -{ - const char * const mux_name[] = {"none", "usb", "dp", "dock"}; - char *e; - int port; - enum typec_mux mux = TYPEC_MUX_NONE; - int i; - - if (argc == 2 && !strcasecmp(argv[1], "debug")) { - enable_debug_prints = 1; - return EC_SUCCESS; - } - - if (argc < 2) - return EC_ERROR_PARAM_COUNT; - - port = strtoi(argv[1], &e, 10); - if (*e || port >= board_get_usb_pd_port_count()) - return EC_ERROR_PARAM1; - - if (argc < 3) { - mux_state_t mux_state; - - mux_state = usb_mux_get(port); - ccprintf("Port %d: USB=%d DP=%d POLARITY=%s HPD_IRQ=%d " - "HPD_LVL=%d SAFE=%d\n", port, - !!(mux_state & USB_PD_MUX_USB_ENABLED), - !!(mux_state & USB_PD_MUX_DP_ENABLED), - mux_state & USB_PD_MUX_POLARITY_INVERTED ? - "INVERTED" : "NORMAL", - !!(mux_state & USB_PD_MUX_HPD_IRQ), - !!(mux_state & USB_PD_MUX_HPD_LVL), - !!(mux_state & USB_PD_MUX_SAFE_MODE)); - - return EC_SUCCESS; - } - - for (i = 0; i < ARRAY_SIZE(mux_name); i++) - if (!strcasecmp(argv[2], mux_name[i])) - mux = i; - usb_mux_set(port, mux, mux == TYPEC_MUX_NONE ? - USB_SWITCH_DISCONNECT : - USB_SWITCH_CONNECT, - pd_get_polarity(port)); - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(typec, command_typec, - "[port|debug] [none|usb|dp|dock]", - "Control type-C connector muxing"); -#endif - -static enum ec_status hc_usb_pd_mux_info(struct host_cmd_handler_args *args) -{ - const struct ec_params_usb_pd_mux_info *p = args->params; - struct ec_response_usb_pd_mux_info *r = args->response; - int port = p->port; - const struct usb_mux *mux; - - if (port >= board_get_usb_pd_port_count()) - return EC_RES_INVALID_PARAM; - - mux = &usb_muxes[port]; - if (mux->driver->get(port, &r->flags) != EC_SUCCESS) - return EC_RES_ERROR; - - /* Clear HPD IRQ event since we're about to inform host of it. */ - if (IS_ENABLED(CONFIG_USB_MUX_VIRTUAL) && - (r->flags & USB_PD_MUX_HPD_IRQ) && - (mux->hpd_update == &virtual_hpd_update)) - mux->hpd_update(port, r->flags & USB_PD_MUX_HPD_LVL, 0); - - args->response_size = sizeof(*r); - return EC_RES_SUCCESS; -} -DECLARE_HOST_COMMAND(EC_CMD_USB_PD_MUX_INFO, - hc_usb_pd_mux_info, - EC_VER_MASK(0)); diff --git a/driver/usb_mux/virtual.c b/driver/usb_mux/virtual.c deleted file mode 100644 index a6e8377ce8..0000000000 --- a/driver/usb_mux/virtual.c +++ /dev/null @@ -1,81 +0,0 @@ -/* 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. - * - * Virtual USB mux driver for host-controlled USB muxes. - */ - -#include "common.h" -#include "console.h" -#include "host_command.h" -#include "usb_mux.h" -#include "util.h" - -/* - * USB PD protocol configures the USB & DP mux state and USB PD policy - * configures the HPD mux state. Both states are independent of each other - * may differ when the PD role changes when in dock mode. - */ -#define USB_PD_MUX_HPD_STATE (USB_PD_MUX_HPD_LVL | USB_PD_MUX_HPD_IRQ) -#define USB_PD_MUX_USB_DP_STATE (USB_PD_MUX_USB_ENABLED | \ - USB_PD_MUX_DP_ENABLED | USB_PD_MUX_POLARITY_INVERTED | \ - USB_PD_MUX_SAFE_MODE) - -static mux_state_t virtual_mux_state[CONFIG_USB_PD_PORT_MAX_COUNT]; - -static inline void virtual_mux_update_state(int port, mux_state_t mux_state) -{ - if (virtual_mux_state[port] != mux_state) { - virtual_mux_state[port] = mux_state; - - host_set_single_event(EC_HOST_EVENT_USB_MUX); - } -} - -static int virtual_init(int port) -{ - return EC_SUCCESS; -} - -/* - * Set the state of our 'virtual' mux. The EC does not actually control this - * mux, so update the desired state, then notify the host of the update. - */ -static int virtual_set_mux(int port, mux_state_t mux_state) -{ - /* Current USB & DP mux status + existing HPD related mux status */ - mux_state_t new_mux_state = (mux_state & ~USB_PD_MUX_HPD_STATE) | - (virtual_mux_state[port] & USB_PD_MUX_HPD_STATE); - - virtual_mux_update_state(port, new_mux_state); - - return EC_SUCCESS; -} - -/* - * Get the state of our 'virtual' mux. Since we the EC does not actually - * control this mux, and the EC has no way of knowing its actual status, - * we return the desired state here. - */ -static int virtual_get_mux(int port, mux_state_t *mux_state) -{ - *mux_state = virtual_mux_state[port]; - - return EC_SUCCESS; -} - -void virtual_hpd_update(int port, int hpd_lvl, int hpd_irq) -{ - /* Current HPD related mux status + existing USB & DP mux status */ - mux_state_t new_mux_state = (hpd_lvl ? USB_PD_MUX_HPD_LVL : 0) | - (hpd_irq ? USB_PD_MUX_HPD_IRQ : 0) | - (virtual_mux_state[port] & USB_PD_MUX_USB_DP_STATE); - - virtual_mux_update_state(port, new_mux_state); -} - -const struct usb_mux_driver virtual_usb_mux_driver = { - .init = virtual_init, - .set = virtual_set_mux, - .get = virtual_get_mux, -}; diff --git a/driver/wpc/p9221.c b/driver/wpc/p9221.c deleted file mode 100644 index 5e98737565..0000000000 --- a/driver/wpc/p9221.c +++ /dev/null @@ -1,808 +0,0 @@ -/* Copyright 2019 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. - */ - -/* - * IDT P9221-R7 Wireless Power Receiver driver. - */ - -#include "p9221.h" -#include "charge_manager.h" -#include "chipset.h" -#include "common.h" -#include "console.h" -#include "gpio.h" -#include "hooks.h" -#include "power.h" -#include "tcpm.h" -#include "timer.h" -#include "usb_charge.h" -#include "usb_pd.h" -#include "util.h" -#include <stdbool.h> -#include "printf.h" - -#define CPRINTS(format, args...) cprints(CC_USBPD, "WPC " format, ## args) - -#define P9221_TX_TIMEOUT_MS (20 * 1000*1000) -#define P9221_DCIN_TIMEOUT_MS (2 * 1000*1000) -#define P9221_VRECT_TIMEOUT_MS (2 * 1000*1000) -#define P9221_NOTIFIER_DELAY_MS (80*1000) -#define P9221R7_ILIM_MAX_UA (1600 * 1000) -#define P9221R7_OVER_CHECK_NUM 3 - -#define OVC_LIMIT 1 -#define OVC_THRESHOLD 1400000 -#define OVC_BACKOFF_LIMIT 900000 -#define OVC_BACKOFF_AMOUNT 100000 - -/* P9221 parameters */ -static struct wpc_charger_info p9221_charger_info = { - .online = false, - .i2c_port = I2C_PORT_WPC, - .pp_buf_valid = false, -}; - -static struct wpc_charger_info *wpc = &p9221_charger_info; - -static void p9221_set_offline(void); - -static const uint32_t p9221_ov_set_lut[] = { - 17000000, 20000000, 15000000, 13000000, - 11000000, 11000000, 11000000, 11000000 -}; - -static int p9221_reg_is_8_bit(uint16_t reg) -{ - switch (reg) { - case P9221_CHIP_REVISION_REG: - case P9221R7_VOUT_SET_REG: - case P9221R7_ILIM_SET_REG: - case P9221R7_CHARGE_STAT_REG: - case P9221R7_EPT_REG: - case P9221R7_SYSTEM_MODE_REG: - case P9221R7_COM_CHAN_RESET_REG: - case P9221R7_COM_CHAN_SEND_SIZE_REG: - case P9221R7_COM_CHAN_SEND_IDX_REG: - case P9221R7_COM_CHAN_RECV_SIZE_REG: - case P9221R7_COM_CHAN_RECV_IDX_REG: - case P9221R7_DEBUG_REG: - case P9221R7_EPP_Q_FACTOR_REG: - case P9221R7_EPP_TX_GUARANTEED_POWER_REG: - case P9221R7_EPP_TX_POTENTIAL_POWER_REG: - case P9221R7_EPP_TX_CAPABILITY_FLAGS_REG: - case P9221R7_EPP_RENEGOTIATION_REG: - case P9221R7_EPP_CUR_RPP_HEADER_REG: - case P9221R7_EPP_CUR_NEGOTIATED_POWER_REG: - case P9221R7_EPP_CUR_MAXIMUM_POWER_REG: - case P9221R7_EPP_CUR_FSK_MODULATION_REG: - case P9221R7_EPP_REQ_RPP_HEADER_REG: - case P9221R7_EPP_REQ_NEGOTIATED_POWER_REG: - case P9221R7_EPP_REQ_MAXIMUM_POWER_REG: - case P9221R7_EPP_REQ_FSK_MODULATION_REG: - case P9221R7_VRECT_TARGET_REG: - case P9221R7_VRECT_KNEE_REG: - case P9221R7_FOD_SECTION_REG: - case P9221R7_VRECT_ADJ_REG: - case P9221R7_ALIGN_X_ADC_REG: - case P9221R7_ALIGN_Y_ADC_REG: - case P9221R7_ASK_MODULATION_DEPTH_REG: - case P9221R7_OVSET_REG: - case P9221R7_EPP_TX_SPEC_REV_REG: - return true; - default: - return false; - } -} - -static int p9221_read8(uint16_t reg, int *val) -{ - return i2c_read_offset16(wpc->i2c_port, P9221_R7_ADDR_FLAGS, - reg, val, 1); -} - -static int p9221_write8(uint16_t reg, int val) -{ - return i2c_write_offset16(wpc->i2c_port, P9221_R7_ADDR_FLAGS, - reg, val, 1); -} - -static int p9221_read16(uint16_t reg, int *val) -{ - return i2c_read_offset16(wpc->i2c_port, P9221_R7_ADDR_FLAGS, - reg, val, 2); -} - -static int p9221_write16(uint16_t reg, int val) -{ - return i2c_write_offset16(wpc->i2c_port, P9221_R7_ADDR_FLAGS, - reg, val, 2); -} - -static int p9221_block_read(uint16_t reg, uint8_t *data, int len) -{ - return i2c_read_offset16_block(wpc->i2c_port, P9221_R7_ADDR_FLAGS, - reg, data, len); -} - -static int p9221_block_write(uint16_t reg, uint8_t *data, int len) -{ - return i2c_write_offset16_block(wpc->i2c_port, P9221_R7_ADDR_FLAGS, - reg, data, len); -} - -static int p9221_set_cmd_reg(uint8_t cmd) -{ - int cur_cmd; - int retry; - int ret; - - for (retry = 0; retry < P9221_COM_CHAN_RETRIES; retry++) { - ret = p9221_read8(P9221_COM_REG, &cur_cmd); - if (ret == EC_SUCCESS && cur_cmd == 0) - break; - msleep(25); - } - - if (retry >= P9221_COM_CHAN_RETRIES) { - CPRINTS("Failed to wait for cmd free %02x", cur_cmd); - return EC_ERROR_TIMEOUT; - } - - ret = p9221_write8(P9221_COM_REG, cmd); - if (ret) - CPRINTS("Failed to set cmd reg %02x: %d", cmd, ret); - - return ret; -} - -/* Convert a register value to uV, Hz, or uA */ -static int p9221_convert_reg_r7(uint16_t reg, uint16_t raw_data, uint32_t *val) -{ - switch (reg) { - case P9221R7_ALIGN_X_ADC_REG: /* raw */ - case P9221R7_ALIGN_Y_ADC_REG: /* raw */ - *val = raw_data; - break; - case P9221R7_VOUT_ADC_REG: /* 12-bit ADC raw */ - case P9221R7_IOUT_ADC_REG: /* 12-bit ADC raw */ - case P9221R7_DIE_TEMP_ADC_REG: /* 12-bit ADC raw */ - case P9221R7_EXT_TEMP_REG: - *val = raw_data & 0xFFF; - break; - case P9221R7_VOUT_SET_REG: /* 0.1V -> uV */ - *val = raw_data * 100 * 1000; - break; - case P9221R7_IOUT_REG: /* mA -> uA */ - case P9221R7_VRECT_REG: /* mV -> uV */ - case P9221R7_VOUT_REG: /* mV -> uV */ - case P9221R7_OP_FREQ_REG: /* kHz -> Hz */ - case P9221R7_TX_PINGFREQ_REG: /* kHz -> Hz */ - *val = raw_data * 1000; - break; - case P9221R7_ILIM_SET_REG: /* 100mA -> uA, 200mA offset */ - *val = ((raw_data * 100) + 200) * 1000; - break; - case P9221R7_OVSET_REG: /* uV */ - raw_data &= P9221R7_OVSET_MASK; - *val = p9221_ov_set_lut[raw_data]; - break; - default: - return -2; - } - - return 0; -} - -static int p9221_reg_read_converted(uint16_t reg, uint32_t *val) -{ - int ret; - int data; - - if (p9221_reg_is_8_bit(reg)) - ret = p9221_read8(reg, &data); - else - ret = p9221_read16(reg, &data); - - if (ret) - return ret; - - return p9221_convert_reg_r7(reg, data, val); -} - -static int p9221_is_online(void) -{ - int chip_id; - - if (p9221_read16(P9221_CHIP_ID_REG, &chip_id) - || chip_id != P9221_CHIP_ID) - return false; - else - return true; -} - -int wpc_chip_is_online(void) -{ - return p9221_is_online(); -} - - -void p9221_interrupt(enum gpio_signal signal) -{ - task_wake(TASK_ID_WPC); -} - -static int p9221r7_clear_interrupts(uint16_t mask) -{ - int ret; - - ret = p9221_write16(P9221R7_INT_CLEAR_REG, mask); - if (ret) { - CPRINTS("Failed to clear INT reg: %d", ret); - return ret; - } - - ret = p9221_set_cmd_reg(P9221_COM_CLEAR_INT_MASK); - if (ret) - CPRINTS("Failed to reset INT: %d", ret); - - return ret; -} - -/* - * Enable interrupts on the P9221 R7, note we don't really need to disable - * interrupts since when the device goes out of field, the P9221 is reset. - */ -static int p9221_enable_interrupts_r7(void) -{ - uint16_t mask = 0; - int ret; - - CPRINTS("Enable interrupts"); - - mask = P9221R7_STAT_LIMIT_MASK | P9221R7_STAT_CC_MASK - | P9221_STAT_VRECT; - - p9221r7_clear_interrupts(mask); - - ret = p9221_write8(P9221_INT_ENABLE_REG, mask); - if (ret) - CPRINTS("Failed to enable INTs: %d", ret); - return ret; -} - -static int p9221_send_csp(uint8_t status) -{ - int ret; - - CPRINTS("Send CSP=%d", status); - mutex_lock(&wpc->cmd_lock); - - ret = p9221_write8(P9221R7_CHARGE_STAT_REG, status); - if (ret == EC_SUCCESS) - ret = p9221_set_cmd_reg(P9221R7_COM_SENDCSP); - - mutex_unlock(&wpc->cmd_lock); - return ret; -} - -static int p9221_send_eop(uint8_t reason) -{ - int rv; - - CPRINTS("Send EOP reason=%d", reason); - mutex_lock(&wpc->cmd_lock); - - rv = p9221_write8(P9221R7_EPT_REG, reason); - if (rv == EC_SUCCESS) - rv = p9221_set_cmd_reg(P9221R7_COM_SENDEPT); - - mutex_unlock(&wpc->cmd_lock); - return rv; -} - -static void print_current_samples(uint32_t *iout_val, int count) -{ - int i; - char temp[P9221R7_OVER_CHECK_NUM * 9 + 1] = { 0 }; - - for (i = 0; i < count ; i++) - snprintf(temp + i * 9, sizeof(temp) - i * 9, - "%08x ", iout_val[i]); - CPRINTS("OVER IOUT_SAMPLES: %s", temp); -} - - -/* - * Number of times to poll the status to see if the current limit condition - * was transient or not. - */ -static void p9221_limit_handler_r7(uint16_t orign_irq_src) -{ - uint8_t reason; - int i; - int ret; - int ovc_count = 0; - uint32_t iout_val[P9221R7_OVER_CHECK_NUM] = { 0 }; - int irq_src = (int)orign_irq_src; - - CPRINTS("OVER INT: %02x", irq_src); - - if (irq_src & P9221R7_STAT_OVV) { - reason = P9221_EOP_OVER_VOLT; - goto send_eop; - } - - if (irq_src & P9221R7_STAT_OVT) { - reason = P9221_EOP_OVER_TEMP; - goto send_eop; - } - - if ((irq_src & P9221R7_STAT_UV) && !(irq_src & P9221R7_STAT_OVC)) - return; - - reason = P9221_EOP_OVER_CURRENT; - for (i = 0; i < P9221R7_OVER_CHECK_NUM; i++) { - ret = p9221r7_clear_interrupts( - irq_src & P9221R7_STAT_LIMIT_MASK); - msleep(50); - if (ret) - continue; - - ret = p9221_reg_read_converted(P9221R7_IOUT_REG, &iout_val[i]); - if (ret) { - CPRINTS("Failed to read IOUT[%d]: %d", i, ret); - continue; - } else if (iout_val[i] > OVC_THRESHOLD) { - ovc_count++; - } - - ret = p9221_read16(P9221_STATUS_REG, &irq_src); - if (ret) { - CPRINTS("Failed to read status: %d", ret); - continue; - } - - if ((irq_src & P9221R7_STAT_OVC) == 0) { - print_current_samples(iout_val, i + 1); - CPRINTS("OVER condition %04x cleared after %d tries", - irq_src, i); - return; - } - - CPRINTS("OVER status is still %04x, retry", irq_src); - } - - if (ovc_count < OVC_LIMIT) { - print_current_samples(iout_val, P9221R7_OVER_CHECK_NUM); - CPRINTS("ovc_threshold=%d, ovc_count=%d, ovc_limit=%d", - OVC_THRESHOLD, ovc_count, OVC_LIMIT); - return; - } - -send_eop: - CPRINTS("OVER is %04x, sending EOP %d", irq_src, reason); - - ret = p9221_send_eop(reason); - if (ret) - CPRINTS("Failed to send EOP %d: %d", reason, ret); -} - -static void p9221_abort_transfers(void) -{ - wpc->tx_busy = false; - wpc->tx_done = true; - wpc->rx_done = true; - wpc->rx_len = 0; -} - -/* Handler for r7 and R7 chips */ -static void p9221r7_irq_handler(uint16_t irq_src) -{ - int res; - - if (irq_src & P9221R7_STAT_LIMIT_MASK) - p9221_limit_handler_r7(irq_src); - - /* Receive complete */ - if (irq_src & P9221R7_STAT_CCDATARCVD) { - int rxlen = 0; - - res = p9221_read8(P9221R7_COM_CHAN_RECV_SIZE_REG, &rxlen); - if (res) - CPRINTS("Failed to read len: %d", res); - - if (rxlen) { - res = p9221_block_read(P9221R7_DATA_RECV_BUF_START, - wpc->rx_buf, rxlen); - if (res) { - CPRINTS("Failed to read CC data: %d", res); - rxlen = 0; - } - - wpc->rx_len = rxlen; - wpc->rx_done = true; - } - } - - /* Send complete */ - if (irq_src & P9221R7_STAT_CCSENDBUSY) { - wpc->tx_busy = false; - wpc->tx_done = true; - } - - /* Proprietary packet */ - if (irq_src & P9221R7_STAT_PPRCVD) { - res = p9221_block_read(P9221R7_DATA_RECV_BUF_START, - wpc->pp_buf, sizeof(wpc->pp_buf)); - if (res) { - CPRINTS("Failed to read PP: %d", res); - wpc->pp_buf_valid = false; - return; - } - - /* We only care about PP which come with 0x4F header */ - wpc->pp_buf_valid = (wpc->pp_buf[0] == 0x4F); - - hexdump(wpc->pp_buf, sizeof(wpc->pp_buf)); - } - - /* CC Reset complete */ - if (irq_src & P9221R7_STAT_CCRESET) - p9221_abort_transfers(); -} - -static int p9221_is_epp(void) -{ - int ret, reg; - uint32_t vout_uv; - - if (p9221_read8(P9221R7_SYSTEM_MODE_REG, ®) == EC_SUCCESS) - return reg & P9221R7_SYSTEM_MODE_EXTENDED_MASK; - - /* Check based on power supply voltage */ - ret = p9221_reg_read_converted(P9221R7_VOUT_ADC_REG, &vout_uv); - if (ret) { - CPRINTS("Failed to read VOUT_ADC: %d", ret); - return false; - } - - CPRINTS("Voltage is %duV", vout_uv); - if (vout_uv > P9221_EPP_THRESHOLD_UV) - return true; - - return false; -} - -static void p9221_config_fod(void) -{ - - int epp; - uint8_t *fod; - int fod_len; - int ret; - int retries = 3; - - CPRINTS("Config FOD"); - - epp = p9221_is_epp(); - fod_len = epp ? board_get_epp_fod(&fod) : board_get_fod(&fod); - if (!fod_len || !fod) { - CPRINTS("FOD data not found"); - return; - } - - while (retries) { - uint8_t fod_read[fod_len]; - - CPRINTS("Writing %s FOD (n=%d try=%d)", - epp ? "EPP" : "BPP", fod_len, retries); - - ret = p9221_block_write(P9221R7_FOD_REG, fod, fod_len); - if (ret) - goto no_fod; - - /* Verify the FOD has been written properly */ - ret = p9221_block_read(P9221R7_FOD_REG, fod_read, fod_len); - if (ret) - goto no_fod; - - if (memcmp(fod, fod_read, fod_len) == 0) - return; - - hexdump(fod_read, fod_len); - - retries--; - msleep(100); - } - -no_fod: - CPRINTS("Failed to set FOD. retries:%d ret:%d", retries, ret); -} - -static void p9221_set_online(void) -{ - int ret; - - CPRINTS("Set online"); - - wpc->online = true; - - wpc->tx_busy = false; - wpc->tx_done = true; - wpc->rx_done = false; - wpc->charge_supplier = CHARGE_SUPPLIER_WPC_BPP; - - ret = p9221_enable_interrupts_r7(); - if (ret) - CPRINTS("Failed to enable INT: %d", ret); - - /* NOTE: depends on _is_epp() which is not valid until DC_IN */ - p9221_config_fod(); -} - -static void p9221_vbus_check_timeout(void) -{ - CPRINTS("Timeout VBUS, online=%d", wpc->online); - if (wpc->online) - p9221_set_offline(); - -} -DECLARE_DEFERRED(p9221_vbus_check_timeout); - -static void p9221_set_offline(void) -{ - CPRINTS("Set offline"); - - wpc->online = false; - /* Reset PP buf so we can get a new serial number next time around */ - wpc->pp_buf_valid = false; - - p9221_abort_transfers(); - - hook_call_deferred(&p9221_vbus_check_timeout_data, -1); -} - -/* P9221_NOTIFIER_DELAY_MS from VRECTON */ -static int p9221_notifier_check_det(void) -{ - if (wpc->online) - goto done; - - /* send out a FOD but is_epp() is still invalid */ - p9221_set_online(); - - /* Give the vbus 2 seconds to come up. */ - CPRINTS("Waiting VBUS"); - hook_call_deferred(&p9221_vbus_check_timeout_data, -1); - hook_call_deferred(&p9221_vbus_check_timeout_data, - P9221_DCIN_TIMEOUT_MS); - -done: - wpc->p9221_check_det = false; - return 0; -} - -static int p9221_get_charge_supplier(void) -{ - if (!wpc->online) - return EC_ERROR_UNKNOWN; - - if (p9221_is_epp()) { - uint32_t tx_id; - int txmf_id; - int ret; - - wpc->charge_supplier = CHARGE_SUPPLIER_WPC_EPP; - - ret = p9221_read16(P9221R7_EPP_TX_MFG_CODE_REG, &txmf_id); - if (ret || txmf_id != P9221_GPP_TX_MF_ID) - return ret; - - ret = p9221_block_read(P9221R7_PROP_TX_ID_REG, - (uint8_t *) &tx_id, - P9221R7_PROP_TX_ID_SIZE); - if (ret) - return ret; - - if (tx_id & P9221R7_PROP_TX_ID_GPP_MASK) - wpc->charge_supplier = CHARGE_SUPPLIER_WPC_GPP; - - CPRINTS("txmf_id=0x%04x tx_id=0x%08x supplier=%d", - txmf_id, tx_id, wpc->charge_supplier); - } else { - wpc->charge_supplier = CHARGE_SUPPLIER_WPC_BPP; - CPRINTS("supplier=%d", wpc->charge_supplier); - } - - return EC_SUCCESS; -} - -static int p9221_get_icl(int charge_supplier) -{ - switch (charge_supplier) { - case CHARGE_SUPPLIER_WPC_EPP: - case CHARGE_SUPPLIER_WPC_GPP: - return P9221_DC_ICL_EPP_MA; - case CHARGE_SUPPLIER_WPC_BPP: - default: - return P9221_DC_ICL_BPP_MA; - } -} - -static int p9221_get_ivl(int charge_supplier) -{ - switch (charge_supplier) { - case CHARGE_SUPPLIER_WPC_EPP: - case CHARGE_SUPPLIER_WPC_GPP: - return P9221_DC_IVL_EPP_MV; - case CHARGE_SUPPLIER_WPC_BPP: - default: - return P9221_DC_IVL_BPP_MV; - } -} - -static void p9221_update_charger(int type, struct charge_port_info *chg) -{ - if (!chg) - charge_manager_update_dualrole(0, CAP_UNKNOWN); - else - charge_manager_update_dualrole(0, CAP_DEDICATED); - - charge_manager_update_charge(type, 0, chg); -} - -static int p9221_reg_write_converted_r7(uint16_t reg, uint32_t val) -{ - int ret = 0; - uint16_t data; - int i; - /* Do the appropriate conversion */ - switch (reg) { - case P9221R7_ILIM_SET_REG: - /* uA -> 0.1A, offset 0.2A */ - if ((val < 200000) || (val > 1600000)) - return -EC_ERROR_INVAL; - data = (val / (100 * 1000)) - 2; - break; - case P9221R7_VOUT_SET_REG: - /* uV -> 0.1V */ - val /= 1000; - if (val < 3500 || val > 9000) - return -EC_ERROR_INVAL; - data = val / 100; - break; - case P9221R7_OVSET_REG: - /* uV */ - for (i = 0; i < ARRAY_SIZE(p9221_ov_set_lut); i++) { - if (val == p9221_ov_set_lut[i]) - break; - } - if (i == ARRAY_SIZE(p9221_ov_set_lut)) - return -EC_ERROR_INVAL; - data = i; - break; - default: - return -EC_ERROR_INVAL; - } - if (p9221_reg_is_8_bit(reg)) - ret = p9221_write8(reg, data); - else - ret = p9221_write16(reg, data); - return ret; -} - -static int p9221_set_dc_icl(void) -{ - /* Increase the IOUT limit */ - if (p9221_reg_write_converted_r7(P9221R7_ILIM_SET_REG, - P9221R7_ILIM_MAX_UA)) - CPRINTS("%s set rx_iout limit fail.", __func__); - - return EC_SUCCESS; -} - - -static void p9221_notifier_check_vbus(void) -{ - struct charge_port_info chg; - - wpc->p9221_check_vbus = false; - - CPRINTS("%s online:%d vbus:%d", __func__, wpc->online, - wpc->vbus_status); - - /* - * We now have confirmation from DC_IN, kill the timer, p9221_online - * will be set by this function. - */ - hook_call_deferred(&p9221_vbus_check_timeout_data, -1); - - if (wpc->vbus_status) { - /* WPC VBUS on ,Always write FOD, check dc_icl, send CSP */ - p9221_set_dc_icl(); - p9221_config_fod(); - - p9221_send_csp(1); - - /* when wpc vbus attached after 2s, set wpc online */ - if (!wpc->online) - p9221_set_online(); - - /* WPC VBUS on , update charge voltage and current */ - p9221_get_charge_supplier(); - chg.voltage = p9221_get_ivl(wpc->charge_supplier); - chg.current = p9221_get_icl(wpc->charge_supplier); - - p9221_update_charger(wpc->charge_supplier, &chg); - } else { - /* - * Vbus detached, set wpc offline and update wpc charge voltage - * and current to zero. - */ - if (wpc->online) { - p9221_set_offline(); - p9221_update_charger(wpc->charge_supplier, NULL); - } - } - - CPRINTS("check_vbus changed on:%d vbus:%d", wpc->online, - wpc->vbus_status); - -} - -static void p9221_detect_work(void) -{ - - CPRINTS("%s online:%d check_vbus:%d check_det:%d vbus:%d", __func__, - wpc->online, wpc->p9221_check_vbus, wpc->p9221_check_det, - wpc->vbus_status); - - /* Step 1 */ - if (wpc->p9221_check_det) - p9221_notifier_check_det(); - - /* Step 2 */ - if (wpc->p9221_check_vbus) - p9221_notifier_check_vbus(); - -} -DECLARE_DEFERRED(p9221_detect_work); - -void p9221_notify_vbus_change(int vbus) -{ - wpc->p9221_check_vbus = true; - wpc->vbus_status = vbus; - hook_call_deferred(&p9221_detect_work_data, P9221_NOTIFIER_DELAY_MS); -} - -void wireless_power_charger_task(void *u) -{ - while (1) { - int ret, irq_src; - task_wait_event(-1); - - ret = p9221_read16(P9221_INT_REG, &irq_src); - if (ret) { - CPRINTS("Failed to read INT REG"); - continue; - } - - CPRINTS("INT SRC 0x%04x", irq_src); - - if (p9221r7_clear_interrupts(irq_src)) - continue; - - if (irq_src & P9221_STAT_VRECT) { - CPRINTS("VRECTON, online=%d", wpc->online); - if (!wpc->online) { - wpc->p9221_check_det = true; - hook_call_deferred(&p9221_detect_work_data, - P9221_NOTIFIER_DELAY_MS); - } - } - - p9221r7_irq_handler(irq_src); - } -} diff --git a/driver/wpc/p9221.h b/driver/wpc/p9221.h deleted file mode 100644 index 0bb0571b38..0000000000 --- a/driver/wpc/p9221.h +++ /dev/null @@ -1,323 +0,0 @@ -/* Copyright 2018 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. - */ - - -/* - * IDT P9221-R7 Wireless Power Receiver driver definitions. - */ - -#ifndef __P9221_R7_H -#define __P9221_R7_H - -#include "common.h" -#include "gpio.h" -#include "charge_manager.h" -#include "task.h" - - -/* ========== Variant-specific configuration ============ */ - -#define P9221_R7_ADDR_FLAGS 0x61 - -/* - * P9221 common registers - */ -#define P9221_CHIP_ID_REG 0x00 -#define P9221_CHIP_ID 0x9220 -#define P9221_CHIP_REVISION_REG 0x02 -#define P9221_CUSTOMER_ID_REG 0x03 -#define P9221R7_CUSTOMER_ID_VAL 0x05 -#define P9221_OTP_FW_MAJOR_REV_REG 0x04 -#define P9221_OTP_FW_MINOR_REV_REG 0x06 -#define P9221_OTP_FW_DATE_REG 0x08 -#define P9221_OTP_FW_DATE_SIZE 12 -#define P9221_OTP_FW_TIME_REG 0x14 -#define P9221_OTP_FW_TIME_SIZE 8 -#define P9221_SRAM_FW_MAJOR_REV_REG 0x1C -#define P9221_SRAM_FW_MINOR_REV_REG 0x1E -#define P9221_SRAM_FW_DATE_REG 0x20 -#define P9221_SRAM_FW_DATE_SIZE 12 -#define P9221_SRAM_FW_TIME_REG 0x2C -#define P9221_SRAM_FW_TIME_SIZE 8 -#define P9221_STATUS_REG 0x34 -#define P9221_INT_REG 0x36 -#define P9221_INT_MASK 0xF7 -#define P9221_INT_ENABLE_REG 0x38 -#define P9221_GPP_TX_MF_ID 0x0072 - -/* - * P9221 Rx registers (x != 5) - */ -#define P9221_CHARGE_STAT_REG 0x3A -#define P9221_EPT_REG 0x3B -#define P9221_VOUT_ADC_REG 0x3C -#define P9221_VOUT_ADC_MASK 0x0FFF -#define P9221_VOUT_SET_REG 0x3E -#define P9221_MAX_VOUT_SET_MV_DEFAULT 9000 -#define P9221_VRECT_ADC_REG 0x40 -#define P9221_VRECT_ADC_MASK 0x0FFF -#define P9221_OVSET_REG 0x42 -#define P9221_OVSET_MASK 0x70 -#define P9221_OVSET_SHIFT 4 -#define P9221_RX_IOUT_REG 0x44 -#define P9221_DIE_TEMP_ADC_REG 0x46 -#define P9221_DIE_TEMP_ADC_MASK 0x0FFF -#define P9221_OP_FREQ_REG 0x48 -#define P9221_ILIM_SET_REG 0x4A -#define P9221_ALIGN_X_ADC_REG 0x4B -#define P9221_ALIGN_Y_ADC_REG 0x4C -#define P9221_OP_MODE_REG 0x4D -#define P9221_COM_REG 0x4E -#define P9221_FW_SWITCH_KEY_REG 0x4F -#define P9221_INT_CLEAR_REG 0x56 -#define P9221_RXID_REG 0x5C -#define P9221_RXID_LEN 6 -#define P9221_MPREQ_REG 0x5C -#define P9221_MPREQ_LEN 6 -#define P9221_FOD_REG 0x68 -#define P9221_NUM_FOD 16 -#define P9221_RX_RAWIOUT_REG 0x7A -#define P9221_RX_RAWIOUT_MASK 0xFFF -#define P9221_PMA_AD_REG 0x7C -#define P9221_RX_PINGFREQ_REG 0xFC -#define P9221_RX_PINGFREQ_MASK 0xFFF -#define P9221_LAST_REG 0xFF - -/* - * P9221R7 unique registers - */ -#define P9221R7_INT_CLEAR_REG 0x3A -#define P9221R7_VOUT_SET_REG 0x3C -#define P9221R7_ILIM_SET_REG 0x3D -#define P9221R7_ILIM_SET_MAX 0x0E /* 0x0E = 1.6A */ -#define P9221R7_CHARGE_STAT_REG 0x3E -#define P9221R7_EPT_REG 0x3F -#define P9221R7_VRECT_REG 0x40 -#define P9221R7_VOUT_REG 0x42 -#define P9221R7_IOUT_REG 0x44 -#define P9221R7_OP_FREQ_REG 0x48 -#define P9221R7_SYSTEM_MODE_REG 0x4C -#define P9221R7_COM_CHAN_RESET_REG 0x50 -#define P9221R7_COM_CHAN_SEND_SIZE_REG 0x58 -#define P9221R7_COM_CHAN_SEND_IDX_REG 0x59 -#define P9221R7_COM_CHAN_RECV_SIZE_REG 0x5A -#define P9221R7_COM_CHAN_RECV_IDX_REG 0x5B -#define P9221R7_VRECT_ADC_REG 0x60 -#define P9221R7_VOUT_ADC_REG 0x62 -#define P9221R7_VOUT_ADC_MASK 0xFFF -#define P9221R7_IOUT_ADC_REG 0x64 -#define P9221R7_IOUT_ADC_MASK 0xFFF -#define P9221R7_DIE_TEMP_ADC_REG 0x66 -#define P9221R7_DIE_TEMP_ADC_MASK 0xFFF -#define P9221R7_AC_PERIOD_REG 0x68 -#define P9221R7_TX_PINGFREQ_REG 0x6A -#define P9221R7_EXT_TEMP_REG 0x6C -#define P9221R7_EXT_TEMP_MASK 0xFFF -#define P9221R7_FOD_REG 0x70 -#define P9221R7_NUM_FOD 16 -#define P9221R7_DEBUG_REG 0x80 -#define P9221R7_EPP_Q_FACTOR_REG 0x83 -#define P9221R7_EPP_TX_GUARANTEED_POWER_REG 0x84 -#define P9221R7_EPP_TX_POTENTIAL_POWER_REG 0x85 -#define P9221R7_EPP_TX_CAPABILITY_FLAGS_REG 0x86 -#define P9221R7_EPP_RENEGOTIATION_REG 0x87 -#define P9221R7_EPP_CUR_RPP_HEADER_REG 0x88 -#define P9221R7_EPP_CUR_NEGOTIATED_POWER_REG 0x89 -#define P9221R7_EPP_CUR_MAXIMUM_POWER_REG 0x8A -#define P9221R7_EPP_CUR_FSK_MODULATION_REG 0x8B -#define P9221R7_EPP_REQ_RPP_HEADER_REG 0x8C -#define P9221R7_EPP_REQ_NEGOTIATED_POWER_REG 0x8D -#define P9221R7_EPP_REQ_MAXIMUM_POWER_REG 0x8E -#define P9221R7_EPP_REQ_FSK_MODULATION_REG 0x8F -#define P9221R7_VRECT_TARGET_REG 0x90 -#define P9221R7_VRECT_KNEE_REG 0x92 -#define P9221R7_VRECT_CORRECTION_FACTOR_REG 0x93 -#define P9221R7_VRECT_MAX_CORRECTION_FACTOR_REG 0x94 -#define P9221R7_VRECT_MIN_CORRECTION_FACTOR_REG 0x96 -#define P9221R7_FOD_SECTION_REG 0x99 -#define P9221R7_VRECT_ADJ_REG 0x9E -#define P9221R7_ALIGN_X_ADC_REG 0xA0 -#define P9221R7_ALIGN_Y_ADC_REG 0xA1 -#define P9221R7_ASK_MODULATION_DEPTH_REG 0xA2 -#define P9221R7_OVSET_REG 0xA3 -#define P9221R7_OVSET_MASK 0x7 -#define P9221R7_EPP_TX_SPEC_REV_REG 0xA9 -#define P9221R7_EPP_TX_MFG_CODE_REG 0xAA -#define P9221R7_GP0_RESET_VOLT_REG 0xAC -#define P9221R7_GP1_RESET_VOLT_REG 0xAE -#define P9221R7_GP2_RESET_VOLT_REG 0xB0 -#define P9221R7_GP3_RESET_VOLT_REG 0xB2 -#define P9221R7_PROP_TX_ID_REG 0xB4 -#define P9221R7_PROP_TX_ID_SIZE 4 -#define P9221R7_DATA_SEND_BUF_START 0x100 -#define P9221R7_DATA_SEND_BUF_SIZE 0x80 -#define P9221R7_DATA_RECV_BUF_START 0x180 -#define P9221R7_DATA_RECV_BUF_SIZE 0x80 -#define P9221R7_MAX_PP_BUF_SIZE 16 -#define P9221R7_LAST_REG 0x1FF - -/* - * System Mode Mask (r7+/0x4C) - */ -#define P9221R7_SYSTEM_MODE_EXTENDED_MASK (1 << 3) - -/* - * TX ID GPP Mask (r7+/0xB4->0xB7) - */ -#define P9221R7_PROP_TX_ID_GPP_MASK (1 << 29) - -/* - * Com Channel Commands - */ -#define P9221R7_COM_CHAN_CCRESET BIT(7) -#define P9221_COM_CHAN_RETRIES 5 - -/* - * End of Power packet types - */ -#define P9221_EOP_UNKNOWN 0x00 -#define P9221_EOP_EOC 0x01 -#define P9221_EOP_INTERNAL_FAULT 0x02 -#define P9221_EOP_OVER_TEMP 0x03 -#define P9221_EOP_OVER_VOLT 0x04 -#define P9221_EOP_OVER_CURRENT 0x05 -#define P9221_EOP_BATT_FAIL 0x06 -#define P9221_EOP_RECONFIG 0x07 -#define P9221_EOP_NO_RESPONSE 0x08 -#define P9221_EOP_NEGOTIATION_FAIL 0x0A -#define P9221_EOP_RESTART_POWER 0x0B - -/* - * Command flags - */ -#define P9221R7_COM_RENEGOTIATE P9221_COM_RENEGOTIATE -#define P9221R7_COM_SWITCH2RAM P9221_COM_SWITCH_TO_RAM_MASK -#define P9221R7_COM_CLRINT P9221_COM_CLEAR_INT_MASK -#define P9221R7_COM_SENDCSP P9221_COM_SEND_CHG_STAT_MASK -#define P9221R7_COM_SENDEPT P9221_COM_SEND_EOP_MASK -#define P9221R7_COM_LDOTGL P9221_COM_LDO_TOGGLE -#define P9221R7_COM_CCACTIVATE BIT(0) - -#define P9221_COM_RENEGOTIATE BIT(7) -#define P9221_COM_SWITCH_TO_RAM_MASK BIT(6) -#define P9221_COM_CLEAR_INT_MASK BIT(5) -#define P9221_COM_SEND_CHG_STAT_MASK BIT(4) -#define P9221_COM_SEND_EOP_MASK BIT(3) -#define P9221_COM_LDO_TOGGLE BIT(1) - -/* - * Interrupt/Status flags for P9221 - */ -#define P9221_STAT_VOUT BIT(7) -#define P9221_STAT_VRECT BIT(6) -#define P9221_STAT_ACMISSING BIT(5) -#define P9221_STAT_OV_TEMP BIT(2) -#define P9221_STAT_OV_VOLT BIT(1) -#define P9221_STAT_OV_CURRENT BIT(0) -#define P9221_STAT_LIMIT_MASK (P9221_STAT_OV_TEMP | \ - P9221_STAT_OV_VOLT | \ - P9221_STAT_OV_CURRENT) -/* - * Interrupt/Status flags for P9221R7 - */ -#define P9221R7_STAT_CCRESET BIT(12) -#define P9221R7_STAT_CCERROR BIT(11) -#define P9221R7_STAT_PPRCVD BIT(10) -#define P9221R7_STAT_CCDATARCVD BIT(9) -#define P9221R7_STAT_CCSENDBUSY BIT(8) -#define P9221R7_STAT_VOUTCHANGED BIT(7) -#define P9221R7_STAT_VRECTON BIT(6) -#define P9221R7_STAT_MODECHANGED BIT(5) -#define P9221R7_STAT_UV BIT(3) -#define P9221R7_STAT_OVT BIT(2) -#define P9221R7_STAT_OVV BIT(1) -#define P9221R7_STAT_OVC BIT(0) -#define P9221R7_STAT_MASK 0x1FFF -#define P9221R7_STAT_CC_MASK (P9221R7_STAT_CCRESET | \ - P9221R7_STAT_PPRCVD | \ - P9221R7_STAT_CCERROR | \ - P9221R7_STAT_CCDATARCVD | \ - P9221R7_STAT_CCSENDBUSY) -#define P9221R7_STAT_LIMIT_MASK (P9221R7_STAT_UV | \ - P9221R7_STAT_OVV | \ - P9221R7_STAT_OVT | \ - P9221R7_STAT_OVC) - -#define P9221_DC_ICL_BPP_MA 1000 -#define P9221_DC_ICL_EPP_MA 1100 -#define P9221_DC_IVL_BPP_MV 5000 -#define P9221_DC_IVL_EPP_MV 9000 -#define P9221_EPP_THRESHOLD_UV 7000000 - -#define true 1 -#define false 0 - -struct wpc_charger_info { - uint8_t online; /* wpc is online */ - uint8_t cust_id; /* customer id */ - uint8_t i2c_port; /* i2c port */ - /* Proprietary Packets receive buffer, to get Proprietary data from TX*/ - uint8_t pp_buf[P9221R7_MAX_PP_BUF_SIZE]; - uint8_t pp_buf_valid; - /* Common message Packets receive buffer, for get data from TX */ - uint8_t rx_buf[P9221R7_DATA_RECV_BUF_SIZE]; - uint8_t rx_len; - uint8_t rx_done; - /* Message packets send buffer, used when send messages from RX to TX*/ - uint8_t tx_buf[P9221R7_DATA_SEND_BUF_SIZE]; - uint8_t tx_id; /* TX device id */ - uint8_t tx_len; /* The data size need send to TX */ - uint8_t tx_done; /* TX data send has done */ - uint8_t tx_busy; /* when tx_busy=1, can't transfer data from RX to TX */ - /* p9221_check_vbus=1 when VBUS has changed, need update charge state */ - uint8_t p9221_check_vbus; - /* p9221_check_det=1 when TX device has detected */ - uint8_t p9221_check_det; - /* vbus_status is 1 when VBUS attached and is 0 when VBUS detached*/ - uint8_t vbus_status; - /* supplier type of wireless charger */ - uint8_t charge_supplier; - /* lock of send command to p9221 */ - struct mutex cmd_lock; -}; - -/* Interrupt handler for p9221 */ -void p9221_interrupt(enum gpio_signal signal); - -/** - * notify p9221 detect update charger status when VBUS changed - * - * @param vbus: new status of VBUS, 1 if VBUS on, 0 if VBUS off. - */ -void p9221_notify_vbus_change(int vbus); - -/** - * get the fod (foreign-object detection) parameters for bpp charger type - * - * @param fod: return the real value of fod paramerters, - * return NULL if fod paramerters not set. - * - * @return the count bytes of fod paramerters. - */ -int board_get_fod(uint8_t **fod); - -/** - * get the fod (foreign-object detection) parameters for epp chager type - * - * @param fod: return the real value of fod paramerters, - * return NULL if fod paramerters not set. - * - * @return the count bytes of fod paramerters. - */ -int board_get_epp_fod(uint8_t **fod); - -/** - * return the wireless charge online status - * - * @return true if online, false if offline. - */ -int wpc_chip_is_online(void); - -#endif |