Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6ffb55e5 authored by Lorenzo Bianconi's avatar Lorenzo Bianconi Committed by Jonathan Cameron
Browse files

iio: imu: st_lsm6dsx: introduce ST_LSM6DSX_ID_EXT sensor ids



Add ST_LSM6DSX_ID_EXT{0,1,2} sensor ids as reference for slave devices
connected to st_lsm6dsx i2c controller. Moreover introduce odr dependency
between accel and ext devices since i2c embedded controller relies on the
accelerometer sensor as bus read/write trigger so we need to enable accel
device at odr = max(accel_odr, ext_odr) in order to properly communicate
with i2c slave devices

Signed-off-by: default avatarLorenzo Bianconi <lorenzo.bianconi@redhat.com>
Signed-off-by: default avatarJonathan Cameron <Jonathan.Cameron@huawei.com>
parent d40464f3
Loading
Loading
Loading
Loading
+4 −1
Original line number Original line Diff line number Diff line
@@ -105,8 +105,11 @@ struct st_lsm6dsx_settings {
};
};


enum st_lsm6dsx_sensor_id {
enum st_lsm6dsx_sensor_id {
	ST_LSM6DSX_ID_ACC,
	ST_LSM6DSX_ID_GYRO,
	ST_LSM6DSX_ID_GYRO,
	ST_LSM6DSX_ID_ACC,
	ST_LSM6DSX_ID_EXT0,
	ST_LSM6DSX_ID_EXT1,
	ST_LSM6DSX_ID_EXT2,
	ST_LSM6DSX_ID_MAX,
	ST_LSM6DSX_ID_MAX,
};
};


+15 −0
Original line number Original line Diff line number Diff line
@@ -102,6 +102,9 @@ static void st_lsm6dsx_get_max_min_odr(struct st_lsm6dsx_hw *hw,


	*max_odr = 0, *min_odr = ~0;
	*max_odr = 0, *min_odr = ~0;
	for (i = 0; i < ST_LSM6DSX_ID_MAX; i++) {
	for (i = 0; i < ST_LSM6DSX_ID_MAX; i++) {
		if (!hw->iio_devs[i])
			continue;

		sensor = iio_priv(hw->iio_devs[i]);
		sensor = iio_priv(hw->iio_devs[i]);


		if (!(hw->enable_mask & BIT(sensor->id)))
		if (!(hw->enable_mask & BIT(sensor->id)))
@@ -125,6 +128,9 @@ static int st_lsm6dsx_update_decimators(struct st_lsm6dsx_hw *hw)
	for (i = 0; i < ST_LSM6DSX_ID_MAX; i++) {
	for (i = 0; i < ST_LSM6DSX_ID_MAX; i++) {
		const struct st_lsm6dsx_reg *dec_reg;
		const struct st_lsm6dsx_reg *dec_reg;


		if (!hw->iio_devs[i])
			continue;

		sensor = iio_priv(hw->iio_devs[i]);
		sensor = iio_priv(hw->iio_devs[i]);
		/* update fifo decimators and sample in pattern */
		/* update fifo decimators and sample in pattern */
		if (hw->enable_mask & BIT(sensor->id)) {
		if (hw->enable_mask & BIT(sensor->id)) {
@@ -232,6 +238,9 @@ int st_lsm6dsx_update_watermark(struct st_lsm6dsx_sensor *sensor, u16 watermark)
		return 0;
		return 0;


	for (i = 0; i < ST_LSM6DSX_ID_MAX; i++) {
	for (i = 0; i < ST_LSM6DSX_ID_MAX; i++) {
		if (!hw->iio_devs[i])
			continue;

		cur_sensor = iio_priv(hw->iio_devs[i]);
		cur_sensor = iio_priv(hw->iio_devs[i]);


		if (!(hw->enable_mask & BIT(cur_sensor->id)))
		if (!(hw->enable_mask & BIT(cur_sensor->id)))
@@ -278,6 +287,9 @@ static int st_lsm6dsx_reset_hw_ts(struct st_lsm6dsx_hw *hw)
		return err;
		return err;


	for (i = 0; i < ST_LSM6DSX_ID_MAX; i++) {
	for (i = 0; i < ST_LSM6DSX_ID_MAX; i++) {
		if (!hw->iio_devs[i])
			continue;

		sensor = iio_priv(hw->iio_devs[i]);
		sensor = iio_priv(hw->iio_devs[i]);
		/*
		/*
		 * store enable buffer timestamp as reference for
		 * store enable buffer timestamp as reference for
@@ -695,6 +707,9 @@ int st_lsm6dsx_fifo_setup(struct st_lsm6dsx_hw *hw)
	}
	}


	for (i = 0; i < ST_LSM6DSX_ID_MAX; i++) {
	for (i = 0; i < ST_LSM6DSX_ID_MAX; i++) {
		if (!hw->iio_devs[i])
			continue;

		buffer = devm_iio_kfifo_allocate(hw->dev);
		buffer = devm_iio_kfifo_allocate(hw->dev);
		if (!buffer)
		if (!buffer)
			return -ENOMEM;
			return -ENOMEM;
+69 −8
Original line number Original line Diff line number Diff line
@@ -450,7 +450,11 @@ int st_lsm6dsx_check_odr(struct st_lsm6dsx_sensor *sensor, u16 odr, u8 *val)
	int i;
	int i;


	for (i = 0; i < ST_LSM6DSX_ODR_LIST_SIZE; i++)
	for (i = 0; i < ST_LSM6DSX_ODR_LIST_SIZE; i++)
		if (st_lsm6dsx_odr_table[sensor->id].odr_avl[i].hz == odr)
		/*
		 * ext devices can run at different odr respect to
		 * accel sensor
		 */
		if (st_lsm6dsx_odr_table[sensor->id].odr_avl[i].hz >= odr)
			break;
			break;


	if (i == ST_LSM6DSX_ODR_LIST_SIZE)
	if (i == ST_LSM6DSX_ODR_LIST_SIZE)
@@ -461,19 +465,67 @@ int st_lsm6dsx_check_odr(struct st_lsm6dsx_sensor *sensor, u16 odr, u8 *val)
	return 0;
	return 0;
}
}


static int st_lsm6dsx_set_odr(struct st_lsm6dsx_sensor *sensor, u16 odr)
static u16 st_lsm6dsx_check_odr_dependency(struct st_lsm6dsx_hw *hw, u16 odr,
					   enum st_lsm6dsx_sensor_id id)
{
{
	struct st_lsm6dsx_sensor *ref = iio_priv(hw->iio_devs[id]);

	if (odr > 0) {
		if (hw->enable_mask & BIT(id))
			return max_t(u16, ref->odr, odr);
		else
			return odr;
	} else {
		return (hw->enable_mask & BIT(id)) ? ref->odr : 0;
	}
}

static int st_lsm6dsx_set_odr(struct st_lsm6dsx_sensor *sensor, u16 req_odr)
{
	struct st_lsm6dsx_sensor *ref_sensor = sensor;
	struct st_lsm6dsx_hw *hw = sensor->hw;
	struct st_lsm6dsx_hw *hw = sensor->hw;
	const struct st_lsm6dsx_reg *reg;
	const struct st_lsm6dsx_reg *reg;
	unsigned int data;
	unsigned int data;
	u8 val = 0;
	int err;
	int err;
	u8 val;


	err = st_lsm6dsx_check_odr(sensor, odr, &val);
	switch (sensor->id) {
	case ST_LSM6DSX_ID_EXT0:
	case ST_LSM6DSX_ID_EXT1:
	case ST_LSM6DSX_ID_EXT2:
	case ST_LSM6DSX_ID_ACC: {
		u16 odr;
		int i;

		/*
		 * i2c embedded controller relies on the accelerometer sensor as
		 * bus read/write trigger so we need to enable accel device
		 * at odr = max(accel_odr, ext_odr) in order to properly
		 * communicate with i2c slave devices
		 */
		ref_sensor = iio_priv(hw->iio_devs[ST_LSM6DSX_ID_ACC]);
		for (i = ST_LSM6DSX_ID_ACC; i < ST_LSM6DSX_ID_MAX; i++) {
			if (!hw->iio_devs[i] || i == sensor->id)
				continue;

			odr = st_lsm6dsx_check_odr_dependency(hw, req_odr, i);
			if (odr != req_odr)
				/* device already configured */
				return 0;
		}
		break;
	}
	default:
		break;
	}

	if (req_odr > 0) {
		err = st_lsm6dsx_check_odr(ref_sensor, req_odr, &val);
		if (err < 0)
		if (err < 0)
			return err;
			return err;
	}


	reg = &st_lsm6dsx_odr_table[sensor->id].reg;
	reg = &st_lsm6dsx_odr_table[ref_sensor->id].reg;
	data = ST_LSM6DSX_SHIFT_VAL(val, reg->mask);
	data = ST_LSM6DSX_SHIFT_VAL(val, reg->mask);
	return st_lsm6dsx_update_bits_locked(hw, reg->addr, reg->mask, data);
	return st_lsm6dsx_update_bits_locked(hw, reg->addr, reg->mask, data);
}
}
@@ -894,7 +946,7 @@ int st_lsm6dsx_probe(struct device *dev, int irq, int hw_id, const char *name,
	if (err < 0)
	if (err < 0)
		return err;
		return err;


	for (i = 0; i < ST_LSM6DSX_ID_MAX; i++) {
	for (i = 0; i < ST_LSM6DSX_ID_EXT0; i++) {
		hw->iio_devs[i] = st_lsm6dsx_alloc_iiodev(hw, i, name);
		hw->iio_devs[i] = st_lsm6dsx_alloc_iiodev(hw, i, name);
		if (!hw->iio_devs[i])
		if (!hw->iio_devs[i])
			return -ENOMEM;
			return -ENOMEM;
@@ -911,6 +963,9 @@ int st_lsm6dsx_probe(struct device *dev, int irq, int hw_id, const char *name,
	}
	}


	for (i = 0; i < ST_LSM6DSX_ID_MAX; i++) {
	for (i = 0; i < ST_LSM6DSX_ID_MAX; i++) {
		if (!hw->iio_devs[i])
			continue;

		err = devm_iio_device_register(hw->dev, hw->iio_devs[i]);
		err = devm_iio_device_register(hw->dev, hw->iio_devs[i]);
		if (err)
		if (err)
			return err;
			return err;
@@ -929,6 +984,9 @@ static int __maybe_unused st_lsm6dsx_suspend(struct device *dev)
	int i, err = 0;
	int i, err = 0;


	for (i = 0; i < ST_LSM6DSX_ID_MAX; i++) {
	for (i = 0; i < ST_LSM6DSX_ID_MAX; i++) {
		if (!hw->iio_devs[i])
			continue;

		sensor = iio_priv(hw->iio_devs[i]);
		sensor = iio_priv(hw->iio_devs[i]);
		if (!(hw->enable_mask & BIT(sensor->id)))
		if (!(hw->enable_mask & BIT(sensor->id)))
			continue;
			continue;
@@ -954,6 +1012,9 @@ static int __maybe_unused st_lsm6dsx_resume(struct device *dev)
	int i, err = 0;
	int i, err = 0;


	for (i = 0; i < ST_LSM6DSX_ID_MAX; i++) {
	for (i = 0; i < ST_LSM6DSX_ID_MAX; i++) {
		if (!hw->iio_devs[i])
			continue;

		sensor = iio_priv(hw->iio_devs[i]);
		sensor = iio_priv(hw->iio_devs[i]);
		if (!(hw->enable_mask & BIT(sensor->id)))
		if (!(hw->enable_mask & BIT(sensor->id)))
			continue;
			continue;