iio: adc: ti-ads1015: Use guard(mutex) and factor out code for INFO_RAW

By use of automatic lock release and introducing a new utility
function to handle the core activity of reading the ADC channel,
many more complex code flows can be replaced by direct returns.

Cc: Marek Vasut <marex@denx.de>
Reviewed-by: David Lechner <dlechner@baylibre.com>
Link: https://patch.msgid.link/20250309165819.1346684-6-jic23@kernel.org
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
This commit is contained in:
Jonathan Cameron
2025-03-09 16:58:16 +00:00
parent 3ba3800286
commit 5655ba5ada

View File

@@ -12,6 +12,7 @@
*/
#include <linux/module.h>
#include <linux/cleanup.h>
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/i2c.h>
@@ -533,6 +534,31 @@ static int ads1015_read_avail(struct iio_dev *indio_dev,
}
}
static int __ads1015_read_info_raw(struct ads1015_data *data,
struct iio_chan_spec const *chan, int *val)
{
int ret;
if (ads1015_event_channel_enabled(data) &&
data->event_channel != chan->address)
return -EBUSY;
ret = ads1015_set_power_state(data, true);
if (ret < 0)
return ret;
ret = ads1015_get_adc_result(data, chan->address, val);
if (ret < 0) {
ads1015_set_power_state(data, false);
return ret;
}
*val = sign_extend32(*val >> chan->scan_type.shift,
chan->scan_type.realbits - 1);
return ads1015_set_power_state(data, false);
}
static int ads1015_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan, int *val,
int *val2, long mask)
@@ -540,58 +566,30 @@ static int ads1015_read_raw(struct iio_dev *indio_dev,
int ret, idx;
struct ads1015_data *data = iio_priv(indio_dev);
mutex_lock(&data->lock);
guard(mutex)(&data->lock);
switch (mask) {
case IIO_CHAN_INFO_RAW:
ret = iio_device_claim_direct_mode(indio_dev);
if (ret)
break;
if (ads1015_event_channel_enabled(data) &&
data->event_channel != chan->address) {
ret = -EBUSY;
goto release_direct;
}
ret = ads1015_set_power_state(data, true);
if (ret < 0)
goto release_direct;
ret = ads1015_get_adc_result(data, chan->address, val);
if (ret < 0) {
ads1015_set_power_state(data, false);
goto release_direct;
}
*val = sign_extend32(*val >> chan->scan_type.shift,
chan->scan_type.realbits - 1);
ret = ads1015_set_power_state(data, false);
if (ret < 0)
goto release_direct;
ret = IIO_VAL_INT;
release_direct:
return ret;
ret = __ads1015_read_info_raw(data, chan, val);
iio_device_release_direct_mode(indio_dev);
break;
if (ret)
return ret;
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
idx = data->channel_data[chan->address].pga;
*val = ads1015_fullscale_range[idx];
*val2 = chan->scan_type.realbits - 1;
ret = IIO_VAL_FRACTIONAL_LOG2;
break;
return IIO_VAL_FRACTIONAL_LOG2;
case IIO_CHAN_INFO_SAMP_FREQ:
idx = data->channel_data[chan->address].data_rate;
*val = data->chip->data_rate[idx];
ret = IIO_VAL_INT;
break;
return IIO_VAL_INT;
default:
ret = -EINVAL;
break;
return -EINVAL;
}
mutex_unlock(&data->lock);
return ret;
}
static int ads1015_write_raw(struct iio_dev *indio_dev,
@@ -599,23 +597,16 @@ static int ads1015_write_raw(struct iio_dev *indio_dev,
int val2, long mask)
{
struct ads1015_data *data = iio_priv(indio_dev);
int ret;
mutex_lock(&data->lock);
guard(mutex)(&data->lock);
switch (mask) {
case IIO_CHAN_INFO_SCALE:
ret = ads1015_set_scale(data, chan, val, val2);
break;
return ads1015_set_scale(data, chan, val, val2);
case IIO_CHAN_INFO_SAMP_FREQ:
ret = ads1015_set_data_rate(data, chan->address, val);
break;
return ads1015_set_data_rate(data, chan->address, val);
default:
ret = -EINVAL;
break;
return -EINVAL;
}
mutex_unlock(&data->lock);
return ret;
}
static int ads1015_read_event(struct iio_dev *indio_dev,
@@ -624,20 +615,18 @@ static int ads1015_read_event(struct iio_dev *indio_dev,
int *val2)
{
struct ads1015_data *data = iio_priv(indio_dev);
int ret;
unsigned int comp_queue;
int period;
int dr;
mutex_lock(&data->lock);
guard(mutex)(&data->lock);
switch (info) {
case IIO_EV_INFO_VALUE:
*val = (dir == IIO_EV_DIR_RISING) ?
data->thresh_data[chan->address].high_thresh :
data->thresh_data[chan->address].low_thresh;
ret = IIO_VAL_INT;
break;
return IIO_VAL_INT;
case IIO_EV_INFO_PERIOD:
dr = data->channel_data[chan->address].data_rate;
comp_queue = data->thresh_data[chan->address].comp_queue;
@@ -646,16 +635,10 @@ static int ads1015_read_event(struct iio_dev *indio_dev,
*val = period / USEC_PER_SEC;
*val2 = period % USEC_PER_SEC;
ret = IIO_VAL_INT_PLUS_MICRO;
break;
return IIO_VAL_INT_PLUS_MICRO;
default:
ret = -EINVAL;
break;
return -EINVAL;
}
mutex_unlock(&data->lock);
return ret;
}
static int ads1015_write_event(struct iio_dev *indio_dev,
@@ -666,24 +649,22 @@ static int ads1015_write_event(struct iio_dev *indio_dev,
struct ads1015_data *data = iio_priv(indio_dev);
const int *data_rate = data->chip->data_rate;
int realbits = chan->scan_type.realbits;
int ret = 0;
long long period;
int i;
int dr;
mutex_lock(&data->lock);
guard(mutex)(&data->lock);
switch (info) {
case IIO_EV_INFO_VALUE:
if (val >= 1 << (realbits - 1) || val < -1 << (realbits - 1)) {
ret = -EINVAL;
break;
}
if (val >= 1 << (realbits - 1) || val < -1 << (realbits - 1))
return -EINVAL;
if (dir == IIO_EV_DIR_RISING)
data->thresh_data[chan->address].high_thresh = val;
else
data->thresh_data[chan->address].low_thresh = val;
break;
return 0;
case IIO_EV_INFO_PERIOD:
dr = data->channel_data[chan->address].data_rate;
period = val * USEC_PER_SEC + val2;
@@ -694,15 +675,10 @@ static int ads1015_write_event(struct iio_dev *indio_dev,
break;
}
data->thresh_data[chan->address].comp_queue = i;
break;
return 0;
default:
ret = -EINVAL;
break;
return -EINVAL;
}
mutex_unlock(&data->lock);
return ret;
}
static int ads1015_read_event_config(struct iio_dev *indio_dev,
@@ -710,25 +686,19 @@ static int ads1015_read_event_config(struct iio_dev *indio_dev,
enum iio_event_direction dir)
{
struct ads1015_data *data = iio_priv(indio_dev);
int ret = 0;
mutex_lock(&data->lock);
if (data->event_channel == chan->address) {
switch (dir) {
case IIO_EV_DIR_RISING:
ret = 1;
break;
case IIO_EV_DIR_EITHER:
ret = (data->comp_mode == ADS1015_CFG_COMP_MODE_WINDOW);
break;
default:
ret = -EINVAL;
break;
}
guard(mutex)(&data->lock);
if (data->event_channel != chan->address)
return 0;
switch (dir) {
case IIO_EV_DIR_RISING:
return 1;
case IIO_EV_DIR_EITHER:
return (data->comp_mode == ADS1015_CFG_COMP_MODE_WINDOW);
default:
return -EINVAL;
}
mutex_unlock(&data->lock);
return ret;
}
static int ads1015_enable_event_config(struct ads1015_data *data,
@@ -813,14 +783,12 @@ static int ads1015_write_event_config(struct iio_dev *indio_dev,
int comp_mode = (dir == IIO_EV_DIR_EITHER) ?
ADS1015_CFG_COMP_MODE_WINDOW : ADS1015_CFG_COMP_MODE_TRAD;
mutex_lock(&data->lock);
guard(mutex)(&data->lock);
/* Prevent from enabling both buffer and event at a time */
ret = iio_device_claim_direct_mode(indio_dev);
if (ret) {
mutex_unlock(&data->lock);
if (ret)
return ret;
}
if (state)
ret = ads1015_enable_event_config(data, chan, comp_mode);
@@ -828,8 +796,6 @@ static int ads1015_write_event_config(struct iio_dev *indio_dev,
ret = ads1015_disable_event_config(data, chan, comp_mode);
iio_device_release_direct_mode(indio_dev);
mutex_unlock(&data->lock);
return ret;
}