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

Commit 0528b19d authored by Mitja Spes's avatar Mitja Spes Committed by Greg Kroah-Hartman
Browse files

iio: pressure: ms5611: fixed value compensation bug



[ Upstream commit 17f442e7e47579d3881fc4d47354eaef09302e6f ]

When using multiple instances of this driver the compensation PROM was
overwritten by the last initialized sensor. Now each sensor has own PROM
storage.

Signed-off-by: default avatarMitja Spes <mitja@lxnav.com>
Fixes: 9690d81a ("iio: pressure: ms5611: add support for MS5607 temperature and pressure sensor")
Link: https://lore.kernel.org/r/20221021135827.1444793-2-mitja@lxnav.com


Cc: <Stable@vger.kernel.org>
Signed-off-by: default avatarJonathan Cameron <Jonathan.Cameron@huawei.com>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent 562f415b
Loading
Loading
Loading
Loading
+4 −8
Original line number Diff line number Diff line
@@ -25,13 +25,6 @@ enum {
	MS5607,
};

struct ms5611_chip_info {
	u16 prom[MS5611_PROM_WORDS_NB];

	int (*temp_and_pressure_compensate)(struct ms5611_chip_info *chip_info,
					    s32 *temp, s32 *pressure);
};

/*
 * OverSampling Rate descriptor.
 * Warning: cmd MUST be kept aligned on a word boundary (see
@@ -50,12 +43,15 @@ struct ms5611_state {
	const struct ms5611_osr *pressure_osr;
	const struct ms5611_osr *temp_osr;

	u16 prom[MS5611_PROM_WORDS_NB];

	int (*reset)(struct ms5611_state *st);
	int (*read_prom_word)(struct ms5611_state *st, int index, u16 *word);
	int (*read_adc_temp_and_pressure)(struct ms5611_state *st,
					  s32 *temp, s32 *pressure);

	struct ms5611_chip_info *chip_info;
	int (*compensate_temp_and_pressure)(struct ms5611_state *st, s32 *temp,
					  s32 *pressure);
	struct regulator *vdd;
};

+27 −24
Original line number Diff line number Diff line
@@ -85,7 +85,7 @@ static int ms5611_read_prom(struct iio_dev *indio_dev)
	struct ms5611_state *st = iio_priv(indio_dev);

	for (i = 0; i < MS5611_PROM_WORDS_NB; i++) {
		ret = st->read_prom_word(st, i, &st->chip_info->prom[i]);
		ret = st->read_prom_word(st, i, &st->prom[i]);
		if (ret < 0) {
			dev_err(&indio_dev->dev,
				"failed to read prom at %d\n", i);
@@ -93,7 +93,7 @@ static int ms5611_read_prom(struct iio_dev *indio_dev)
		}
	}

	if (!ms5611_prom_is_valid(st->chip_info->prom, MS5611_PROM_WORDS_NB)) {
	if (!ms5611_prom_is_valid(st->prom, MS5611_PROM_WORDS_NB)) {
		dev_err(&indio_dev->dev, "PROM integrity check failed\n");
		return -ENODEV;
	}
@@ -114,21 +114,20 @@ static int ms5611_read_temp_and_pressure(struct iio_dev *indio_dev,
		return ret;
	}

	return st->chip_info->temp_and_pressure_compensate(st->chip_info,
							   temp, pressure);
	return st->compensate_temp_and_pressure(st, temp, pressure);
}

static int ms5611_temp_and_pressure_compensate(struct ms5611_chip_info *chip_info,
static int ms5611_temp_and_pressure_compensate(struct ms5611_state *st,
					       s32 *temp, s32 *pressure)
{
	s32 t = *temp, p = *pressure;
	s64 off, sens, dt;

	dt = t - (chip_info->prom[5] << 8);
	off = ((s64)chip_info->prom[2] << 16) + ((chip_info->prom[4] * dt) >> 7);
	sens = ((s64)chip_info->prom[1] << 15) + ((chip_info->prom[3] * dt) >> 8);
	dt = t - (st->prom[5] << 8);
	off = ((s64)st->prom[2] << 16) + ((st->prom[4] * dt) >> 7);
	sens = ((s64)st->prom[1] << 15) + ((st->prom[3] * dt) >> 8);

	t = 2000 + ((chip_info->prom[6] * dt) >> 23);
	t = 2000 + ((st->prom[6] * dt) >> 23);
	if (t < 2000) {
		s64 off2, sens2, t2;

@@ -154,17 +153,17 @@ static int ms5611_temp_and_pressure_compensate(struct ms5611_chip_info *chip_inf
	return 0;
}

static int ms5607_temp_and_pressure_compensate(struct ms5611_chip_info *chip_info,
static int ms5607_temp_and_pressure_compensate(struct ms5611_state *st,
					       s32 *temp, s32 *pressure)
{
	s32 t = *temp, p = *pressure;
	s64 off, sens, dt;

	dt = t - (chip_info->prom[5] << 8);
	off = ((s64)chip_info->prom[2] << 17) + ((chip_info->prom[4] * dt) >> 6);
	sens = ((s64)chip_info->prom[1] << 16) + ((chip_info->prom[3] * dt) >> 7);
	dt = t - (st->prom[5] << 8);
	off = ((s64)st->prom[2] << 17) + ((st->prom[4] * dt) >> 6);
	sens = ((s64)st->prom[1] << 16) + ((st->prom[3] * dt) >> 7);

	t = 2000 + ((chip_info->prom[6] * dt) >> 23);
	t = 2000 + ((st->prom[6] * dt) >> 23);
	if (t < 2000) {
		s64 off2, sens2, t2, tmp;

@@ -342,15 +341,6 @@ static int ms5611_write_raw(struct iio_dev *indio_dev,

static const unsigned long ms5611_scan_masks[] = {0x3, 0};

static struct ms5611_chip_info chip_info_tbl[] = {
	[MS5611] = {
		.temp_and_pressure_compensate = ms5611_temp_and_pressure_compensate,
	},
	[MS5607] = {
		.temp_and_pressure_compensate = ms5607_temp_and_pressure_compensate,
	}
};

static const struct iio_chan_spec ms5611_channels[] = {
	{
		.type = IIO_PRESSURE,
@@ -433,7 +423,20 @@ int ms5611_probe(struct iio_dev *indio_dev, struct device *dev,
	struct ms5611_state *st = iio_priv(indio_dev);

	mutex_init(&st->lock);
	st->chip_info = &chip_info_tbl[type];

	switch (type) {
	case MS5611:
		st->compensate_temp_and_pressure =
			ms5611_temp_and_pressure_compensate;
		break;
	case MS5607:
		st->compensate_temp_and_pressure =
			ms5607_temp_and_pressure_compensate;
		break;
	default:
		return -EINVAL;
	}

	st->temp_osr =
		&ms5611_avail_temp_osr[ARRAY_SIZE(ms5611_avail_temp_osr) - 1];
	st->pressure_osr =