- Driver starts the measurement on the background when it is
probed. This improves the respnse time to read-requests
compared to starting the read only when data is requested.
When the most accurate 400 mS measurement time is used, data reads
would last quite long if measurement was started only on
demand. This, however, is not appealing for users who would
prefere power saving over measurement response time.
+static bool bu27034_has_valid_sample(struct bu27034_data *data)
+{
+ int ret, val;
+
+ ret = regmap_read(data->regmap, BU27034_REG_MODE_CONTROL4, &val);
+ if (ret)
+ dev_err(data->dev, "Read failed %d\n", ret);
+
+ return (val & BU27034_MASK_VALID);
+}
+
+static void bu27034_invalidate_read_data(struct bu27034_data *data)
+{
+ bu27034_has_valid_sample(data);
+}
+
+static int _bu27034_get_result(struct bu27034_data *data, u16 *res, bool lock)
+{
+ int ret = 0;
+
+retry:
+ if (lock)
+ mutex_lock(&data->mutex);
+ /* Get new value from sensor if data is ready - or use cached value */
+ if (bu27034_has_valid_sample(data)) {
+ ret = regmap_bulk_read(data->regmap, BU27034_REG_DATA0_LO,
+ &data->raw[0], sizeof(data->raw));
+ if (ret)
+ goto unlock_out;
+
+ data->cached = true;
+ bu27034_invalidate_read_data(data);
+ } else if (unlikely(!data->cached)) {
+ /* No new data in sensor and no value cached. Wait and retry */
+ if (lock)
+ mutex_unlock(&data->mutex);
+ msleep(25);
+
+ goto retry;
+ }
+ res[0] = le16_to_cpu(data->raw[0]);
+ res[1] = le16_to_cpu(data->raw[1]);
+ res[2] = le16_to_cpu(data->raw[2]);
+
+unlock_out:
+ if (lock)
+ mutex_unlock(&data->mutex);
+
+ return ret;
+}
+
+static int bu27034_get_result_unlocked(struct bu27034_data *data, u16 *res)
+{
+ return _bu27034_get_result(data, res, false);
+}
+
+static int bu27034_get_result(struct bu27034_data *data, u16 *res)
+{
+ return _bu27034_get_result(data, res, true);
+}
+ case IIO_CHAN_INFO_RAW:
+ {
+ u16 res[3];
+
+ if (chan->type != IIO_INTENSITY)
+ return -EINVAL;
+
+ if (chan->channel < BU27034_CHAN_DATA0 ||
+ chan->channel > BU27034_CHAN_DATA2)
+ return -EINVAL;
+ /*
+ * Reading one channel at a time is inefficient.
+ *
+ * Hence we run the measurement on the background and always
+ * read all the channels. There are following caveats:
+ * 1) The VALID bit handling is racy. Valid bit clearing is not
+ * tied to reading the data in the hardware. We clear the
+ * valid-bit manually _after_ we have read the data - but this
+ * means there is a small time-window where new result may
+ * arrive between read and clear. This means we can miss a
+ * sample. For normal use this should not be fatal because
+ * usually the light is changing slowly. There might be
+ * use-cases for measuring more rapidly changing light but this
+ * driver is unsuitable for those cases anyways. (Smallest
+ * measurement time we support is 55 mS.)
+ * 2) Data readings more frequent than the meas_time will return
+ * the same cached values. This should not be a problem for the
+ * very same reason 1) is not a problem.
+ */
+ ret = bu27034_get_result(data, &res[0]);
+ if (ret)
+ return ret;
+
+ *val = res[chan->channel - BU27034_CHAN_DATA0];
+
+ return IIO_VAL_INT;
+ }
+static int bu27034_chip_init(struct bu27034_data *data)
+{
+
+ /*
+ * Consider disabling the measurement (and powering off the sensor) for
+ * runtime pm
+ */
+ ret = bu27034_meas_en(data);
+ if (ret)
+ return ret;
+
+ return devm_add_action_or_reset(data->dev, bu27034_meas_stop, data);
+}