<commit_before>/* 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->addr, reg, &tmp);
	if (ret != EC_SUCCESS)
		return ret;

	tmp |= bit_field;
	return st_raw_write8(s->port, s->addr, 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->addr, reg, &tmp);
	if (ret != EC_SUCCESS)
		return ret;

	tmp &= ~(bit_field);
	return st_raw_write8(s->port, s->addr, 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->addr, 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->addr, 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->addr, 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->addr, 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->addr,
			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->addr, 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->addr, 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->addr,
				LSM6DSM_CTRL1_ADDR, cache);
}

static int config_slv0_read(const struct motion_sensor_t *s, uint8_t addr,
						uint8_t reg, uint8_t len)
{
	int ret;

	ret = st_raw_write8(s->port, s->addr, LSM6DSM_SLV0_ADD_ADDR,
			(addr << LSM6DSM_SLV0_ADDR_SHFT) | 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->addr, LSM6DSM_SLV0_SUBADD_ADDR, reg);
	if (ret != EC_SUCCESS) {
		CPRINTF("%s: %s type:0x%x RA error ret: %d\n",<commit_msg>driver/sensorhub_lsm6dsm: fix sensorhub mode slv0 address<commit_after>/* 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->addr, reg, &tmp);
	if (ret != EC_SUCCESS)
		return ret;

	tmp |= bit_field;
	return st_raw_write8(s->port, s->addr, 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->addr, reg, &tmp);
	if (ret != EC_SUCCESS)
		return ret;

	tmp &= ~(bit_field);
	return st_raw_write8(s->port, s->addr, 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->addr, 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->addr, 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->addr, 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->addr, 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->addr,
			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->addr, 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->addr, 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->addr,
				LSM6DSM_CTRL1_ADDR, cache);
}

static int config_slv0_read(const struct motion_sensor_t *s, uint8_t addr,
						uint8_t reg, uint8_t len)
{
	int ret;

	ret = st_raw_write8(s->port, s->addr, LSM6DSM_SLV0_ADD_ADDR,
			(addr | 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->addr, LSM6DSM_SLV0_SUBADD_ADDR, reg);
	if (ret != EC_SUCCESS) {
		CPRINTF("%s: %s type:0x%x RA error ret: %d\n",
{'fraction_non_alphanumeric': 0.1135600335852225, 'fraction_numerical': 0.01910159529806885, 'mean_word_length': 4.582308142940832, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 79, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '327814', 'n_tokens_mistral': 4163, 'n_tokens_neox': 3872, 'n_words': 931}