Re: [PATCH v3 1/2] iio: temperature: mlx90635 MLX90635 IR Temperature sensor

From: Jonathan Cameron
Date: Sun Dec 10 2023 - 07:14:38 EST


On Wed, 6 Dec 2023 21:49:33 +0100
Crt Mori <cmo@xxxxxxxxxxx> wrote:

> MLX90635 is an Infra Red contactless temperature sensor most suitable
> for consumer applications where measured object temperature is in range
> between -20 to 100 degrees Celsius. It has improved accuracy for
> measurements within temperature range of human body and can operate in
> ambient temperature range between -20 to 85 degrees Celsius.
>
> Driver provides simple power management possibility as it returns to
> lowest possible power mode (Step sleep mode) in which temperature
> measurements can still be performed, yet for continuous measuring it
> switches to Continuous power mode where measurements constantly change
> without triggering.
>
> Signed-off-by: Crt Mori<cmo@xxxxxxxxxxx>
Nice work

I've made a few comments inline for future possible improvements, but
given the cleanup.h stuff is fairly new I'll not block this merging based
on that.

I made some tiny tweak for readability whilst applying. Please sanity check
that. diff was all about return values that must be 0 as they come out of regmap and
we've already checked for error cases.
diff --git a/drivers/iio/temperature/mlx90635.c b/drivers/iio/temperature/mlx90635.c
index 1b3bde36f18a..1f5c962c1818 100644
--- a/drivers/iio/temperature/mlx90635.c
+++ b/drivers/iio/temperature/mlx90635.c
@@ -306,7 +306,7 @@ static int mlx90635_read_ee_ambient(struct regmap *regmap, s16 *PG, s16 *PO, s16
return ret;
*Gb = (u16)read_tmp;

- return ret;
+ return 0;
}

static int mlx90635_read_ee_object(struct regmap *regmap, u32 *Ea, u32 *Eb, u32 *Fa, s16 *Fb,
@@ -357,7 +357,7 @@ static int mlx90635_read_ee_object(struct regmap *regmap, u32 *Ea, u32 *Eb, u32
return ret;
*Fa_scale = (u16)read_tmp;

- return ret;
+ return 0;
}

static int mlx90635_calculate_dataset_ready_time(struct mlx90635_data *data, int *refresh_time)
@@ -405,7 +405,7 @@ static int mlx90635_perform_measurement_burst(struct mlx90635_data *data)
return -ETIMEDOUT;
}

- return ret;
+ return 0;
}

static int mlx90635_read_ambient_raw(struct regmap *regmap,
@@ -424,7 +424,7 @@ static int mlx90635_read_ambient_raw(struct regmap *regmap,
return ret;
*ambient_old_raw = (s16)read_tmp;

- return ret;
+ return 0;
}

static int mlx90635_read_object_raw(struct regmap *regmap, s16 *object_raw)
@@ -444,7 +444,7 @@ static int mlx90635_read_object_raw(struct regmap *regmap, s16 *object_raw)
return ret;
*object_raw = (read - (s16)read_tmp) / 2;

- return ret;
+ return 0;
}


Applied to the togreg branch of iio.git and pushed out as testing for all the normal
reasons.

> diff --git a/drivers/iio/temperature/mlx90635.c b/drivers/iio/temperature/mlx90635.c
> new file mode 100644
> index 000000000000..1b3bde36f18a
> --- /dev/null
> +++ b/drivers/iio/temperature/mlx90635.c


> +static int mlx90635_perform_measurement_burst(struct mlx90635_data *data)
> +{
> + unsigned int reg_status;
> + int refresh_time;
> + int ret;
> +
> + ret = regmap_write_bits(data->regmap, MLX90635_REG_STATUS,
> + MLX90635_STAT_END_CONV, MLX90635_STAT_END_CONV);
> + if (ret < 0)
> + return ret;
> +
> + ret = mlx90635_calculate_dataset_ready_time(data, &refresh_time);
> + if (ret < 0)
> + return ret;
> +
> + ret = regmap_write_bits(data->regmap, MLX90635_REG_CTRL2,
> + FIELD_PREP(MLX90635_CTRL2_SOB_MASK, 1),
> + FIELD_PREP(MLX90635_CTRL2_SOB_MASK, 1));
> + if (ret < 0)
> + return ret;
> +
> + msleep(refresh_time); /* Wait minimum time for dataset to be ready */
> +
> + ret = regmap_read_poll_timeout(data->regmap, MLX90635_REG_STATUS, reg_status,
> + (!(reg_status & MLX90635_STAT_END_CONV)) == 0,
> + MLX90635_TIMING_POLLING, MLX90635_READ_RETRIES * 10000);
> + if (ret < 0) {
> + dev_err(&data->client->dev, "data not ready");
> + return -ETIMEDOUT;
> + }
> +
> + return ret;
I'll tweak this one to return 0 to make it explicit that no postive values
are returned.

> +}


> +static int mlx90635_read_all_channel(struct mlx90635_data *data,
> + s16 *ambient_new_raw, s16 *ambient_old_raw,
> + s16 *object_raw)
> +{
> + int ret;
> +
> + mutex_lock(&data->lock);
> + if (data->powerstatus == MLX90635_PWR_STATUS_SLEEP_STEP) {
> + /* Trigger measurement in Sleep Step mode */
> + ret = mlx90635_perform_measurement_burst(data);
> + if (ret < 0)
> + goto read_unlock;
> + }
> +
> + ret = mlx90635_read_ambient_raw(data->regmap, ambient_new_raw,
> + ambient_old_raw);
> + if (ret < 0)
> + goto read_unlock;
> +
> + ret = mlx90635_read_object_raw(data->regmap, object_raw);
> +read_unlock:
> + mutex_unlock(&data->lock);

A good function to use guard(mutex)(&data->lock)

> + return ret;
> +}
> +

> +static int mlx90635_calc_ambient(struct mlx90635_data *data, int *val)
> +{
> + s16 ambient_new_raw, ambient_old_raw;
> + s16 PG, PO, Gb;
> + int ret;
> +
> + ret = mlx90635_read_ee_ambient(data->regmap_ee, &PG, &PO, &Gb);
> + if (ret < 0)
> + return ret;
> +
> + mutex_lock(&data->lock);
I don't mind this not changing for now, but this is exactly the
sort of place for scoped_guard()
Something like:

scoped_guard(mutex, &data->lock) {
if (data->powerstatus == MLX90635_PWR_STATUS_SLEEP_STEP) {
ret = mlx90635_perform_measurement_burst(data);
if (ret < 0)
return ret;
}

ret = mlx90635_read_ambient_raw(data->regmap, &ambient_new_raw,
&ambient_old_raw);
if (ret < 0)
return ret;
}

> + if (data->powerstatus == MLX90635_PWR_STATUS_SLEEP_STEP) {
> + ret = mlx90635_perform_measurement_burst(data);
> + if (ret < 0)
> + goto read_ambient_unlock;
> + }
> +
> + ret = mlx90635_read_ambient_raw(data->regmap, &ambient_new_raw,
> + &ambient_old_raw);
> +read_ambient_unlock:
> + mutex_unlock(&data->lock);
> + if (ret < 0)
> + return ret;
> +
> + *val = mlx90635_calc_temp_ambient(ambient_new_raw, ambient_old_raw,
> + PG, PO, Gb);
> + return ret;
> +}