On Tue, 23 May 2023 17:12:19 +0200 Herve Codina <herve.codina@xxxxxxxxxxx> wrote: > A helper, iio_read_max_channel_raw() exists to read the available > maximum raw value of a channel but nothing similar exists to read the > available minimum raw value. > > This new helper, iio_read_min_channel_raw(), fills the hole and can be > used for reading the available minimum raw value of a channel. > It is fully based on the existing iio_read_max_channel_raw(). > > Signed-off-by: Herve Codina <herve.codina@xxxxxxxxxxx> Acked-by: Jonathan Cameron <Jonathan.Cameron@xxxxxxxxxx> > --- > drivers/iio/inkern.c | 70 ++++++++++++++++++++++++++++++++++++ > include/linux/iio/consumer.h | 12 +++++++ > 2 files changed, 82 insertions(+) > > diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c > index f738db9a0c04..07b26ff8a334 100644 > --- a/drivers/iio/inkern.c > +++ b/drivers/iio/inkern.c > @@ -915,6 +915,76 @@ int iio_read_max_channel_raw(struct iio_channel *chan, int *val) > } > EXPORT_SYMBOL_GPL(iio_read_max_channel_raw); > > +static int iio_channel_read_min(struct iio_channel *chan, > + int *val, int *val2, int *type, > + enum iio_chan_info_enum info) > +{ > + int unused; > + const int *vals; > + int length; > + int ret; > + > + if (!val2) > + val2 = &unused; > + > + ret = iio_channel_read_avail(chan, &vals, type, &length, info); > + if (ret < 0) > + return ret; > + > + switch (ret) { > + case IIO_AVAIL_RANGE: > + switch (*type) { > + case IIO_VAL_INT: > + *val = vals[0]; > + break; > + default: > + *val = vals[0]; > + *val2 = vals[1]; > + } > + return 0; > + > + case IIO_AVAIL_LIST: > + if (length <= 0) > + return -EINVAL; > + switch (*type) { > + case IIO_VAL_INT: > + *val = vals[--length]; > + while (length) { > + if (vals[--length] < *val) > + *val = vals[length]; > + } > + break; > + default: > + /* FIXME: learn about min for other iio values */ > + return -EINVAL; > + } > + return 0; > + > + default: > + return -EINVAL; > + } > +} > + > +int iio_read_min_channel_raw(struct iio_channel *chan, int *val) > +{ > + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(chan->indio_dev); > + int ret; > + int type; > + > + mutex_lock(&iio_dev_opaque->info_exist_lock); > + if (!chan->indio_dev->info) { > + ret = -ENODEV; > + goto err_unlock; > + } > + > + ret = iio_channel_read_min(chan, val, NULL, &type, IIO_CHAN_INFO_RAW); > +err_unlock: > + mutex_unlock(&iio_dev_opaque->info_exist_lock); > + > + return ret; > +} > +EXPORT_SYMBOL_GPL(iio_read_min_channel_raw); > + > int iio_get_channel_type(struct iio_channel *chan, enum iio_chan_type *type) > { > struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(chan->indio_dev); > diff --git a/include/linux/iio/consumer.h b/include/linux/iio/consumer.h > index f536820b9cf2..e9910b41d48e 100644 > --- a/include/linux/iio/consumer.h > +++ b/include/linux/iio/consumer.h > @@ -301,6 +301,18 @@ int iio_write_channel_raw(struct iio_channel *chan, int val); > */ > int iio_read_max_channel_raw(struct iio_channel *chan, int *val); > > +/** > + * iio_read_min_channel_raw() - read minimum available raw value from a given > + * channel, i.e. the minimum possible value. > + * @chan: The channel being queried. > + * @val: Value read back. > + * > + * Note, if standard units are required, raw reads from iio channels > + * need the offset (default 0) and scale (default 1) to be applied > + * as (raw + offset) * scale. > + */ > +int iio_read_min_channel_raw(struct iio_channel *chan, int *val); > + > /** > * iio_read_avail_channel_raw() - read available raw values from a given channel > * @chan: The channel being queried.