diff options
| author | Joshua Crofts <joshua.crofts1@gmail.com> | 2026-07-14 17:36:48 +0200 |
|---|---|---|
| committer | Jonathan Cameron <jonathan.cameron@oss.qualcomm.com> | 2026-07-20 02:47:44 +0100 |
| commit | 176790d0d6e78026eb350de8a5943b289db82bd0 (patch) | |
| tree | 656c3b39621dc4e11b60ba86dd100c80ed2999c2 | |
| parent | 1c286917a27aa72e4486eca79e0cdab8d67717b3 (diff) | |
| download | linux-176790d0d6e78026eb350de8a5943b289db82bd0.tar.gz linux-176790d0d6e78026eb350de8a5943b289db82bd0.zip | |
iio: light: opt3001: split opt3001_get_processed() logic
Split the logic inside the opt3001_get_processed() function, as the
current flow is hard to read, mixing IRQ and non-IRQ code blocks.
Separate the IRQ code path into its own function, same for the
non-IRQ path.
Suggested-by: Jonathan Cameron <jic23@kernel.org>
Signed-off-by: Joshua Crofts <joshua.crofts1@gmail.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@intel.com>
Signed-off-by: Jonathan Cameron <jonathan.cameron@oss.qualcomm.com>
| -rw-r--r-- | drivers/iio/light/opt3001.c | 188 |
1 files changed, 104 insertions, 84 deletions
diff --git a/drivers/iio/light/opt3001.c b/drivers/iio/light/opt3001.c index 434ef7e034fe..a948353014ac 100644 --- a/drivers/iio/light/opt3001.c +++ b/drivers/iio/light/opt3001.c @@ -315,35 +315,12 @@ static const struct iio_chan_spec opt3002_channels[] = { IIO_CHAN_SOFT_TIMESTAMP(1), }; -static int opt3001_get_processed(struct opt3001 *opt, int *val, int *val2) +static int opt3001_start_conversion(struct opt3001 *opt) { struct i2c_client *client = opt->client; struct device *dev = &client->dev; - int ret; - u16 mantissa; u16 reg; - u8 exponent; - u16 value; - long timeout; - - if (opt->use_irq) { - /* - * Enable the end-of-conversion interrupt mechanism. Note that - * doing so will overwrite the low-level limit value however we - * will restore this value later on. - */ - ret = i2c_smbus_write_word_swapped(client, - OPT3001_LOW_LIMIT, - OPT3001_LOW_LIMIT_EOC_ENABLE); - if (ret < 0) { - dev_err(dev, "failed to write register %02x\n", - OPT3001_LOW_LIMIT); - return ret; - } - - /* Allow IRQ to access the device despite lock being set */ - opt->ok_to_ignore_lock = true; - } + int ret; /* Reset data-ready indicator flag */ opt->result_ready = false; @@ -353,85 +330,128 @@ static int opt3001_get_processed(struct opt3001 *opt, int *val, int *val2) if (ret < 0) { dev_err(dev, "failed to read register %02x\n", OPT3001_CONFIGURATION); - goto err; + return ret; } reg = ret; opt3001_set_mode(opt, ®, OPT3001_CONFIGURATION_M_SINGLE); ret = i2c_smbus_write_word_swapped(client, OPT3001_CONFIGURATION, reg); - if (ret < 0) { + if (ret) dev_err(dev, "failed to write register %02x\n", OPT3001_CONFIGURATION); - goto err; - } - - if (opt->use_irq) { - /* Wait for the IRQ to indicate the conversion is complete */ - ret = wait_event_timeout(opt->result_ready_queue, - opt->result_ready, - msecs_to_jiffies(OPT3001_RESULT_READY_LONG)); - if (ret == 0) { - ret = -ETIMEDOUT; - goto err; - } - } else { - /* Sleep for result ready time */ - timeout = (opt->int_time == OPT3001_INT_TIME_SHORT) ? - OPT3001_RESULT_READY_SHORT : OPT3001_RESULT_READY_LONG; - msleep(timeout); - /* Check result ready flag */ - ret = i2c_smbus_read_word_swapped(client, OPT3001_CONFIGURATION); - if (ret < 0) { - dev_err(dev, "failed to read register %02x\n", - OPT3001_CONFIGURATION); - goto err; - } + return ret; +} - if (!(ret & OPT3001_CONFIGURATION_CRF)) { - ret = -ETIMEDOUT; - goto err; - } +static int opt3001_get_processed_irq(struct opt3001 *opt) +{ + struct i2c_client *client = opt->client; + struct device *dev = &client->dev; + u16 value; + int ret; - /* Obtain value */ - ret = i2c_smbus_read_word_swapped(client, OPT3001_RESULT); - if (ret < 0) { - dev_err(dev, "failed to read register %02x\n", - OPT3001_RESULT); - goto err; - } - opt->result = ret; - opt->result_ready = true; + /* + * Enable the end-of-conversion interrupt mechanism. Note that doing so + * will overwrite the low-level limit value however we will restore this + * value later on. + */ + ret = i2c_smbus_write_word_swapped(client, + OPT3001_LOW_LIMIT, + OPT3001_LOW_LIMIT_EOC_ENABLE); + if (ret < 0) { + dev_err(dev, "failed to write register %02x\n", + OPT3001_LOW_LIMIT); + return ret; } + /* Allow IRQ to access the device despite lock being set */ + opt->ok_to_ignore_lock = true; + + ret = opt3001_start_conversion(opt); + if (ret) + goto err; + + if (wait_event_timeout(opt->result_ready_queue, opt->result_ready, + msecs_to_jiffies(OPT3001_RESULT_READY_LONG))) + ret = 0; + else + ret = -ETIMEDOUT; + err: - if (opt->use_irq) - /* Disallow IRQ to access the device while lock is active */ - opt->ok_to_ignore_lock = false; + opt->ok_to_ignore_lock = false; if (ret < 0) return ret; - if (opt->use_irq) { - /* - * Disable the end-of-conversion interrupt mechanism by - * restoring the low-level limit value (clearing - * OPT3001_LOW_LIMIT_EOC_ENABLE). Note that selectively clearing - * those enable bits would affect the actual limit value due to - * bit-overlap and therefore can't be done. - */ - value = (opt->low_thresh_exp << 12) | opt->low_thresh_mantissa; - ret = i2c_smbus_write_word_swapped(client, - OPT3001_LOW_LIMIT, - value); - if (ret < 0) { - dev_err(dev, "failed to write register %02x\n", - OPT3001_LOW_LIMIT); - return ret; - } + /* + * Disable the end-of-conversion interrupt mechanism by restoring the + * low-level limit value (clearing OPT3001_LOW_LIMIT_EOC_ENABLE). Note + * that selectively clearing those enable bits would affect the actual + * limit value due to bit-overlap and therefore can't be done. + */ + value = (opt->low_thresh_exp << 12) | opt->low_thresh_mantissa; + ret = i2c_smbus_write_word_swapped(client, OPT3001_LOW_LIMIT, value); + if (ret) + dev_err(dev, "failed to write register %02x\n", + OPT3001_LOW_LIMIT); + + return ret; +} + +static int opt3001_get_processed_noirq(struct opt3001 *opt) +{ + struct i2c_client *client = opt->client; + struct device *dev = &client->dev; + int ret; + + ret = opt3001_start_conversion(opt); + if (ret) + return ret; + + if (opt->int_time == OPT3001_INT_TIME_SHORT) + msleep(OPT3001_RESULT_READY_SHORT); + else + msleep(OPT3001_RESULT_READY_LONG); + + /* Check result ready flag */ + ret = i2c_smbus_read_word_swapped(client, OPT3001_CONFIGURATION); + if (ret < 0) { + dev_err(dev, "failed to read register %02x\n", + OPT3001_CONFIGURATION); + return ret; } + if (!(ret & OPT3001_CONFIGURATION_CRF)) + return -ETIMEDOUT; + + /* Obtain value */ + ret = i2c_smbus_read_word_swapped(client, OPT3001_RESULT); + if (ret < 0) { + dev_err(dev, "failed to read register %02x\n", + OPT3001_RESULT); + return ret; + } + + opt->result = ret; + opt->result_ready = true; + + return 0; +} + +static int opt3001_get_processed(struct opt3001 *opt, int *val, int *val2) +{ + u16 mantissa; + u8 exponent; + int ret; + + if (opt->use_irq) + ret = opt3001_get_processed_irq(opt); + else + ret = opt3001_get_processed_noirq(opt); + if (ret) + return ret; + exponent = OPT3001_REG_EXPONENT(opt->result); mantissa = OPT3001_REG_MANTISSA(opt->result); |
