[PATCH v3 4/5] iio: pressure: ms5637: Parameterise second order temperature compensation

Louis Adamian <[email protected]>
Newsgroups org.kernel.vger.linux-iio,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
The temperature compensation formula is shared across these sensors but
with different constants. Add ms_tp_comp_consts to capture these
per-device differences. Add pressure variant specific pressure scale
variable.

No functional change intended. IIO_VAL_FRACTIONAL prints 3 more decimal
places than IIO_VAL_INT_PLUS_MICRO, giving in_pressure_input 3 more
trailing zeros.

Signed-off-by: Louis Adamian <[email protected]>
---
 .../iio/common/ms_sensors/ms_sensors_i2c.c    | 61 ++++++++++++-------
 .../iio/common/ms_sensors/ms_sensors_i2c.h    | 48 +++++++++++++++
 drivers/iio/pressure/ms5637.c                 | 61 ++++++++++++++++---
 3 files changed, 140 insertions(+), 30 deletions(-)

diff --git a/drivers/iio/common/ms_sensors/ms_sensors_i2c.c b/drivers/iio/common/ms_sensors/ms_sensors_i2c.c
index f9dc7c7468c1..20f019ae51fd 100644
--- a/drivers/iio/common/ms_sensors/ms_sensors_i2c.c
+++ b/drivers/iio/common/ms_sensors/ms_sensors_i2c.c
@@ -604,6 +604,38 @@ int ms_sensors_tp_read_prom(struct ms_tp_dev *dev_data)
 }
 EXPORT_SYMBOL_NS(ms_sensors_tp_read_prom, "IIO_MEAS_SPEC_SENSORS");
 
+/* apply second order temperature compensation */
+static void ms_tp_compensate(const struct ms_tp_comp_consts *c,
+			     s32 temp, s32 dt, s64 *t2, s64 *off2, s64 *sens2)
+{
+	s64 tmp;
+
+	if (temp < 2000) {
+		tmp = temp - 2000;
+		*t2 = (c->low_t2_multiplier * ((s64)dt * (s64)dt)) >>
+		      c->low_t2_shift;
+		*off2 = (c->low_off2_multiplier * tmp * tmp) >>
+			c->low_off2_shift;
+		*sens2 = (c->low_sens2_multiplier * tmp * tmp) >>
+			 c->low_sens2_shift;
+
+		if (temp < -1500) {
+			tmp = temp + 1500;
+			*off2 += c->vlow_off2_multiplier * tmp * tmp;
+			*sens2 += c->vlow_sens2_multiplier * tmp * tmp;
+		}
+	} else {
+		*sens2 = 0;
+		if (c->has_vhigh_temp && temp > 4500)
+			*sens2 -= (((s64)temp - 4500) * ((s64)temp - 4500)) >> 3;
+
+		*t2 = (c->high_t2_multiplier * ((s64)dt * (s64)dt)) >> c->high_t2_shift;
+		*off2 = (c->high_off2_multiplier *
+			 ((s64)temp - 2000) * ((s64)temp - 2000)) >>
+			c->high_off2_shift;
+	}
+}
+
 /**
  * ms_sensors_read_temp_and_pressure() - read temp and pressure
  * @dev_data:	pointer to temperature/pressure device data
@@ -619,6 +651,7 @@ int ms_sensors_read_temp_and_pressure(struct ms_tp_dev *dev_data,
 				      int *temperature,
 				      unsigned int *pressure)
 {
+	const struct ms_tp_comp_consts *c = dev_data->data->comp_consts;
 	int ret;
 	u32 t_adc, p_adc;
 	s32 dt, temp;
@@ -654,37 +687,21 @@ int ms_sensors_read_temp_and_pressure(struct ms_tp_dev *dev_data,
 	/* Actual temperature = 2000 + dT * TEMPSENS */
 	temp = 2000 + (((s64)dt * prom[6]) >> 23);
 
-	/* Second order temperature compensation */
-	if (temp < 2000) {
-		s64 tmp = (s64)temp - 2000;
-
-		t2 = (3 * ((s64)dt * (s64)dt)) >> 33;
-		off2 = (61 * tmp * tmp) >> 4;
-		sens2 = (29 * tmp * tmp) >> 4;
-
-		if (temp < -1500) {
-			s64 tmp = (s64)temp + 1500;
-
-			off2 += 17 * tmp * tmp;
-			sens2 += 9 * tmp * tmp;
-		}
-	} else {
-		t2 = (5 * ((s64)dt * (s64)dt)) >> 38;
-		off2 = 0;
-		sens2 = 0;
-	}
+	ms_tp_compensate(c, temp, dt, &t2, &off2, &sens2);
 
 	/* OFF = OFF_T1 + TCO * dT */
-	off = (((s64)prom[2]) << 17) + ((((s64)prom[4]) * (s64)dt) >> 6);
+	off = (((s64)prom[2]) << c->off_t1_shift) +
+	      ((((s64)prom[4]) * (s64)dt) >> c->off_shift);
 	off -= off2;
 
 	/* Sensitivity at actual temperature = SENS_T1 + TCS * dT */
-	sens = (((s64)prom[1]) << 16) + (((s64)prom[3] * dt) >> 7);
+	sens = (((s64)prom[1]) << c->sens_t1_shift) +
+	       (((s64)prom[3] * dt) >> c->sens_shift);
 	sens -= sens2;
 
 	/* Temperature compensated pressure = D1 * SENS - OFF */
 	*temperature = (temp - t2) * 10;
-	*pressure = (u32)(((((s64)p_adc * sens) >> 21) - off) >> 15);
+	*pressure = (u32)(((((s64)p_adc * sens) >> c->press_sens_shift) - off) >> c->press_shift);
 
 	return 0;
 }
diff --git a/drivers/iio/common/ms_sensors/ms_sensors_i2c.h b/drivers/iio/common/ms_sensors/ms_sensors_i2c.h
index d9898098c066..e6e64111f2e7 100644
--- a/drivers/iio/common/ms_sensors/ms_sensors_i2c.h
+++ b/drivers/iio/common/ms_sensors/ms_sensors_i2c.h
@@ -35,14 +35,62 @@ struct ms_tp_hw_data {
 	u8 max_res_index;
 };
 
+/**
+ * struct ms_tp_comp_consts - Temperature compensation constants
+ * @press_scale: pressure scale
+ * @high_t2_multiplier: multiplier for t2 in high temperature state
+ * @high_t2_shift: bit shift for t2 in high temperature state
+ * @high_off2_multiplier: multiplier for off2 in high temperature state
+ * @high_off2_shift: bit shift for off2 in high temperature state
+ * @low_t2_multiplier: multiplier for t2 in low temperature state
+ * @low_t2_shift: bit shift for t2 in low temperature state
+ * @low_off2_multiplier: multiplier for off2 in low temperature state
+ * @low_off2_shift: bit shift for off2 in low temperature state
+ * @low_sens2_multiplier: multiplier for sens2 in low temperature state
+ * @low_sens2_shift: bit shift for sens2 in low temperature state
+ * @vlow_off2_multiplier: multiplier for value added to off2 in very low temperature state
+ * @vlow_sens2_multiplier: multiplier for value added to sens2 in very low temperature state
+ * @has_vhigh_temp: has very high temperature compensation logic
+ * @off_t1_shift: temperature offset t1 bit shift
+ * @off_shift: temperature offset shift
+ * @sens_t1_shift: temperature sensitivity t1 shift
+ * @sens_shift: temperature sensitivity shift
+ * @press_sens_shift: pressure sensitivity shift
+ * @press_shift: pressure shift
+ */
+struct ms_tp_comp_consts {
+	u32 press_scale;
+	u8 high_t2_multiplier;
+	u8 high_t2_shift;
+	u8 high_off2_multiplier;
+	u8 high_off2_shift;
+	u8 low_t2_multiplier;
+	u8 low_t2_shift;
+	u8 low_off2_multiplier;
+	u8 low_off2_shift;
+	u8 low_sens2_multiplier;
+	u8 low_sens2_shift;
+	u8 vlow_off2_multiplier;
+	u8 vlow_sens2_multiplier;
+	bool has_vhigh_temp;
+	u8 off_t1_shift;
+	u8 off_shift;
+	u8 sens_t1_shift;
+	u8 sens_shift;
+	u8 press_sens_shift;
+	u8 press_shift;
+};
+
 /**
  * struct ms_tp_data - Temperature/Pressure sensor data
  * @name: Device name
  * @hw: Sensor hardware data
+ * @comp_consts: Temperature compensation constants
  */
 struct ms_tp_data {
 	const char *name;
 	const struct ms_tp_hw_data *hw;
+	const struct ms_tp_comp_consts *comp_consts;
 };
 
 /**
diff --git a/drivers/iio/pressure/ms5637.c b/drivers/iio/pressure/ms5637.c
index 6009d87f3d4c..359f3a8e79b2 100644
--- a/drivers/iio/pressure/ms5637.c
+++ b/drivers/iio/pressure/ms5637.c
@@ -67,10 +67,9 @@ static int ms5637_read_raw(struct iio_dev *indio_dev,
 
 			return IIO_VAL_INT;
 		case IIO_PRESSURE:	/* in kPa */
-			*val = pressure / 1000;
-			*val2 = (pressure % 1000) * 1000;
-
-			return IIO_VAL_INT_PLUS_MICRO;
+			*val = pressure;
+			*val2 = dev_data->data->comp_consts->press_scale;
+			return IIO_VAL_FRACTIONAL;
 		default:
 			return -EINVAL;
 		}
@@ -195,17 +194,63 @@ static const struct ms_tp_hw_data ms5803_hw_data  = {
 	.max_res_index = 4
 };
 
-static const struct ms_tp_data ms5637_data = { .name = "ms5637", .hw = &ms5637_hw_data };
+/*
+ * MS5637-02BA03 compensation constants
+ * Datasheet: https://www.te.com/commerce/DocumentDelivery/DDEController?Action=showdoc&DocId=Data+Sheet%7FMS5637-02BA03%7FB1%7Fpdf%7FEnglish%7FENG_DS_MS5637-02BA03_B1.pdf
+ * Pages: 7-8
+ * Sections: Pressure and Temperature Calculation, Second Order Temperature Compensation
+ */
+static const struct ms_tp_comp_consts ms5637_02_consts = {
+	.press_scale = 1000,
+	.high_t2_multiplier = 5,
+	.high_t2_shift = 38,
+	.high_off2_multiplier = 0,
+	.high_off2_shift = 0,
+	.low_t2_multiplier = 3,
+	.low_t2_shift = 33,
+	.low_off2_multiplier = 61,
+	.low_off2_shift = 4,
+	.low_sens2_multiplier = 29,
+	.low_sens2_shift = 4,
+	.vlow_off2_multiplier = 17,
+	.vlow_sens2_multiplier = 9,
+	.has_vhigh_temp = false,
+	.off_t1_shift = 17,
+	.off_shift = 6,
+	.sens_t1_shift = 16,
+	.sens_shift = 7,
+	.press_sens_shift = 21,
+	.press_shift = 15,
+};
+
+static const struct ms_tp_data ms5637_data = {
+	.name = "ms5637",
+	.hw = &ms5637_hw_data,
+	.comp_consts = &ms5637_02_consts,
+};
 
-static const struct ms_tp_data ms5803_data = { .name = "ms5803", .hw = &ms5803_hw_data };
+static const struct ms_tp_data ms5803_data = {
+	.name = "ms5803",
+	.hw = &ms5803_hw_data,
+	.comp_consts = &ms5637_02_consts,
+};
 
-static const struct ms_tp_data ms5805_data = { .name = "ms5805", .hw = &ms5637_hw_data };
+static const struct ms_tp_data ms5805_data = {
+	.name = "ms5805",
+	.hw = &ms5637_hw_data,
+	.comp_consts = &ms5637_02_consts,
+};
 
-static const struct ms_tp_data ms5837_data = { .name = "ms5837", .hw = &ms5637_hw_data };
+static const struct ms_tp_data ms5837_data = {
+	.name = "ms5837",
+	.hw = &ms5637_hw_data,
+	.comp_consts = &ms5637_02_consts,
+};
 
 static const struct ms_tp_data ms8607_data = {
 	.name = "ms8607-temppressure",
 	.hw = &ms5637_hw_data,
+	.comp_consts = &ms5637_02_consts,
 };
 
 static const struct i2c_device_id ms5637_id[] = {
-- 
2.55.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.