mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-10 13:59:45 -04:00
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:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user