summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoshua Crofts <joshua.crofts1@gmail.com>2026-07-14 17:36:48 +0200
committerJonathan Cameron <jonathan.cameron@oss.qualcomm.com>2026-07-20 02:47:44 +0100
commit176790d0d6e78026eb350de8a5943b289db82bd0 (patch)
tree656c3b39621dc4e11b60ba86dd100c80ed2999c2
parent1c286917a27aa72e4486eca79e0cdab8d67717b3 (diff)
downloadlinux-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.c188
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, &reg, 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);