]> rtime.felk.cvut.cz Git - sojka/nv-tegra/linux-3.10.git/commitdiff
iio: light: CM3217 index fix.
authorErik Lilliebjerg <elilliebjerg@nvidia.com>
Fri, 16 Oct 2015 07:56:04 +0000 (00:56 -0700)
committermobile promotions <svcmobile_promotions@nvidia.com>
Sat, 31 Oct 2015 04:57:14 +0000 (21:57 -0700)
- Fix possible table index out-of-bounds.
- Change default threshold values to something in reality.
- Add CM3217 debug light dump.
NVS_IIO v208:
- Add ability to read debug dump from HW driver without a write.
- Add sensor name to debug prints.
- Add functionality to returned calls from HW driver allowing simplification
  of HW driver code, specifically for multi-sensor drivers.

Bug 200145232

Change-Id: I79d014569e236c70d8a3cdec2945fc0f22e43c07
Signed-off-by: Erik Lilliebjerg <elilliebjerg@nvidia.com>
Reviewed-on: http://git-master/r/818914
(cherry picked from commit 2821e9f1d517169d21ac8b18b648afd27bf438a1)
Reviewed-on: http://git-master/r/823562
Reviewed-by: Automatic_Commit_Validation_User
GVS: Gerrit_Virtual_Submit
Reviewed-by: Robert Collins <rcollins@nvidia.com>
Tested-by: Robert Collins <rcollins@nvidia.com>
drivers/iio/common/nvs/nvs_iio.c
drivers/iio/light/nvs_cm3217.c
include/linux/nvs.h

index 0da9bd8299defbaf88bfa8c62e1dbf523d81e026..24d649af87382df9a980bac7e90437cdc35abee7 100644 (file)
@@ -76,7 +76,7 @@
 #include <linux/iio/trigger.h>
 #include <linux/nvs.h>
 
-#define NVS_IIO_DRIVER_VERSION         (207)
+#define NVS_IIO_DRIVER_VERSION         (208)
 #define NVS_ATTRS_ARRAY_SIZE           (12)
 
 enum NVS_ATTR {
@@ -355,6 +355,8 @@ static ssize_t nvs_dbg_cfg(struct iio_dev *indio_dev, char *buf)
        t += sprintf(buf + t, "ch_n=%u\n", st->cfg->ch_n);
        t += sprintf(buf + t, "ch_sz=%d\n", st->cfg->ch_sz);
        t += sprintf(buf + t, "ch_inf=%p\n", st->cfg->ch_inf);
+       t += sprintf(buf + t, "delay_us_min=%u\n", st->cfg->delay_us_min);
+       t += sprintf(buf + t, "delay_us_max=%u\n", st->cfg->delay_us_max);
        t += sprintf(buf + t, "uncal_lo=%d\n", st->cfg->uncal_lo);
        t += sprintf(buf + t, "uncal_hi=%d\n", st->cfg->uncal_hi);
        t += sprintf(buf + t, "cal_lo=%d\n", st->cfg->cal_lo);
@@ -479,12 +481,13 @@ static int nvs_buf_push(struct iio_dev *indio_dev, unsigned char *data, s64 ts)
                st->ts_diff = ts - st->ts;
                st->ts = ts;
                if (st->ts_diff < 0)
-                       dev_err(st->dev, "%s ts_diff=%lld\n",
-                               __func__, st->ts_diff);
+                       dev_err(st->dev, "%s %s ts_diff=%lld\n",
+                               __func__, st->cfg->name, st->ts_diff);
        } else {
                st->flush = false;
                if (*st->fn_dev->sts & (NVS_STS_SPEW_MSG | NVS_STS_SPEW_DATA))
-                       dev_info(st->dev, "%s FLUSH\n", __func__);
+                       dev_info(st->dev, "%s %s FLUSH\n",
+                                __func__, st->cfg->name);
        }
        if (indio_dev->buffer->scan_timestamp) {
                n = sizeof(ts);
@@ -503,15 +506,15 @@ static int nvs_buf_push(struct iio_dev *indio_dev, unsigned char *data, s64 ts)
                }
                if (*st->fn_dev->sts & NVS_STS_SPEW_BUF) {
                        for (i = 0; i < bytes; i++)
-                               dev_info(st->dev, "buf[%u]=%x\n",
-                                        i, st->buf[i]);
-                       dev_info(st->dev,
-                                "ts=%lld  diff=%lld\n", ts, st->ts_diff);
+                               dev_info(st->dev, "%s buf[%u]=%x\n",
+                                        st->cfg->name, i, st->buf[i]);
+                       dev_info(st->dev, "%s ts=%lld  diff=%lld\n",
+                                st->cfg->name, ts, st->ts_diff);
                }
        }
        if ((*st->fn_dev->sts & NVS_STS_SPEW_DATA) && ts) {
                nvs_dbg_data(indio_dev, char_buf);
-               dev_info(st->dev, "%s", char_buf);
+               dev_info(st->dev, "%s %s", st->cfg->name, char_buf);
        }
        if (!ret)
                /* return pushed byte count from data if no error.
@@ -554,7 +557,8 @@ static int nvs_enable(struct iio_dev *indio_dev, bool en)
        if (!ret)
                st->enabled = enable;
        if (*st->fn_dev->sts & NVS_STS_SPEW_MSG)
-               dev_info(st->dev, "%s %d ret=%d", __func__, enable, ret);
+               dev_info(st->dev, "%s %s enable=%d ret=%d",
+                        __func__, st->cfg->name, enable, ret);
        return ret;
 }
 
@@ -635,11 +639,11 @@ static ssize_t nvs_attr_store(struct device *dev,
        mutex_unlock(&indio_dev->mlock);
        if (*st->fn_dev->sts & NVS_STS_SPEW_MSG) {
                if (ret)
-                       dev_err(st->dev, "%s %s %d->%d ERR=%d\n",
-                               __func__, msg, old, new, ret);
+                       dev_err(st->dev, "%s %s %s %d->%d ERR=%d\n",
+                               __func__, st->cfg->name, msg, old, new, ret);
                else
-                       dev_info(st->dev, "%s %s %d->%d\n",
-                                __func__, msg, old, new);
+                       dev_info(st->dev, "%s %s %s %d->%d\n",
+                                __func__, st->cfg->name, msg, old, new);
        }
        if (ret)
                return ret;
@@ -771,7 +775,7 @@ static ssize_t nvs_info_store(struct device *dev,
                                                    st->cfg->snsr_id, dbg);
                        if (ret < 0)
                                return ret;
-               } else {
+               } else if (!st->fn_dev->nvs_read) {
                        st->dbg = NVS_INFO_DATA;
                        return -EINVAL;
                }
@@ -1068,6 +1072,7 @@ static int nvs_write_raw(struct iio_dev *indio_dev,
 {
        struct nvs_state *st = iio_priv(indio_dev);
        char *msg;
+       int ch = chan->scan_index;
        int old = 0;
        int old2 = 0;
        int ret = 0;
@@ -1130,20 +1135,24 @@ static int nvs_write_raw(struct iio_dev *indio_dev,
        case IIO_CHAN_INFO_SCALE:
                msg = "IIO_CHAN_INFO_SCALE";
                if (st->cfg->ch_n_max) {
-                       if (chan->scan_index >= st->cfg->ch_n_max) {
+                       if (ch >= st->cfg->ch_n_max) {
                                ret = -EINVAL;
                                break;
                        }
 
-                       old = st->cfg->scales[chan->scan_index].ival;
-                       old2 = st->cfg->scales[chan->scan_index].fval;
+                       old = st->cfg->scales[ch].ival;
+                       old2 = st->cfg->scales[ch].fval;
                        if (st->fn_dev->scale) {
                                ret = st->fn_dev->scale(st->client,
-                                                       st->cfg->snsr_id,
-                                                       chan->scan_index, val);
+                                                   st->cfg->snsr_id, ch, val);
+                               if (ret > 0) {
+                                       st->cfg->scales[ch].ival = val;
+                                       st->cfg->scales[ch].fval = val2;
+                                       ret = 0;
+                               }
                        } else {
-                               st->cfg->scales[chan->scan_index].ival = val;
-                               st->cfg->scales[chan->scan_index].fval = val2;
+                               st->cfg->scales[ch].ival = val;
+                               st->cfg->scales[ch].fval = val2;
                        }
                } else {
                        old = st->cfg->scale.ival;
@@ -1152,6 +1161,11 @@ static int nvs_write_raw(struct iio_dev *indio_dev,
                                ret = st->fn_dev->scale(st->client,
                                                        st->cfg->snsr_id,
                                                        -1, val);
+                               if (ret > 0) {
+                                       st->cfg->scale.ival = val;
+                                       st->cfg->scale.fval = val2;
+                                       ret = 0;
+                               }
                        } else {
                                st->cfg->scale.ival = val;
                                st->cfg->scale.fval = val2;
@@ -1162,20 +1176,24 @@ static int nvs_write_raw(struct iio_dev *indio_dev,
        case IIO_CHAN_INFO_OFFSET:
                msg = "IIO_CHAN_INFO_OFFSET";
                if (st->cfg->ch_n_max) {
-                       if (chan->scan_index >= st->cfg->ch_n_max) {
+                       if (ch >= st->cfg->ch_n_max) {
                                ret = -EINVAL;
                                break;
                        }
 
-                       old = st->cfg->offsets[chan->scan_index].ival;
-                       old2 = st->cfg->offsets[chan->scan_index].fval;
+                       old = st->cfg->offsets[ch].ival;
+                       old2 = st->cfg->offsets[ch].fval;
                        if (st->fn_dev->offset) {
                                ret = st->fn_dev->offset(st->client,
-                                                        st->cfg->snsr_id,
-                                                       chan->scan_index, val);
+                                                   st->cfg->snsr_id, ch, val);
+                               if (ret > 0) {
+                                       st->cfg->offsets[ch].ival = val;
+                                       st->cfg->offsets[ch].fval = val2;
+                                       ret = 0;
+                               }
                        } else {
-                               st->cfg->offsets[chan->scan_index].ival = val;
-                               st->cfg->offsets[chan->scan_index].fval = val2;
+                               st->cfg->offsets[ch].ival = val;
+                               st->cfg->offsets[ch].fval = val2;
                        }
                } else {
                        old = st->cfg->offset.ival;
@@ -1184,6 +1202,11 @@ static int nvs_write_raw(struct iio_dev *indio_dev,
                                ret = st->fn_dev->offset(st->client,
                                                         st->cfg->snsr_id,
                                                         -1 , val);
+                               if (ret > 0) {
+                                       st->cfg->offset.ival = val;
+                                       st->cfg->offset.fval = val2;
+                                       ret = 0;
+                               }
                        } else {
                                st->cfg->offset.ival = val;
                                st->cfg->offset.fval = val2;
@@ -1194,21 +1217,31 @@ static int nvs_write_raw(struct iio_dev *indio_dev,
        case IIO_CHAN_INFO_THRESHOLD_LOW:
                msg = "IIO_CHAN_INFO_THRESHOLD_LOW";
                old = st->cfg->thresh_lo;
-               if (st->fn_dev->thresh_lo)
+               if (st->fn_dev->thresh_lo) {
                        ret = st->fn_dev->thresh_lo(st->client,
                                                    st->cfg->snsr_id, val);
-               else
+                       if (ret > 0) {
+                               st->cfg->thresh_lo = val;
+                               ret = 0;
+                       }
+               } else {
                        st->cfg->thresh_lo = val;
+               }
                break;
 
        case IIO_CHAN_INFO_THRESHOLD_HIGH:
                msg = "IIO_CHAN_INFO_THRESHOLD_HIGH";
                old = st->cfg->thresh_hi;
-               if (st->fn_dev->thresh_hi)
+               if (st->fn_dev->thresh_hi) {
                        ret = st->fn_dev->thresh_hi(st->client,
                                                    st->cfg->snsr_id, val);
-               else
+                       if (ret > 0) {
+                               st->cfg->thresh_hi = val;
+                               ret = 0;
+                       }
+               } else {
                        st->cfg->thresh_hi = val;
+               }
                break;
 
        case IIO_CHAN_INFO_PEAK:
@@ -1218,6 +1251,11 @@ static int nvs_write_raw(struct iio_dev *indio_dev,
                if (st->fn_dev->max_range) {
                        ret = st->fn_dev->max_range(st->client,
                                                    st->cfg->snsr_id, val);
+                       if (ret > 0) {
+                               st->cfg->max_range.ival = val;
+                               st->cfg->max_range.fval = val2;
+                               ret = 0;
+                       }
                } else {
                        st->cfg->max_range.ival = val;
                        st->cfg->max_range.fval = val2;
@@ -1231,6 +1269,11 @@ static int nvs_write_raw(struct iio_dev *indio_dev,
                if (st->fn_dev->resolution) {
                        ret = st->fn_dev->resolution(st->client,
                                                     st->cfg->snsr_id, val);
+                       if (ret > 0) {
+                               st->cfg->resolution.ival = val;
+                               st->cfg->resolution.fval = val2;
+                               ret = 0;
+                       }
                } else {
                        st->cfg->resolution.ival = val;
                        st->cfg->resolution.fval = val2;
@@ -1239,15 +1282,15 @@ static int nvs_write_raw(struct iio_dev *indio_dev,
 
        case IIO_CHAN_INFO_RAW:
                /* writing to raw is a debug feature allowing a sticky data
-                  value to be pushed up and the same value pushed until the
-                  device is turned off.
+                * value to be pushed up and the same value pushed until the
+                * device is turned off.
                 */
                msg = "IIO_CHAN_INFO_RAW";
-               ret = nvs_buf_i(indio_dev, chan->scan_index);
+               ret = nvs_buf_i(indio_dev, ch);
                if (ret >= 0) {
                        memcpy(&st->buf[ret], &val,
                               chan->scan_type.storagebits / 8);
-                       st->dbg_data_lock |= (1 << chan->scan_index);
+                       st->dbg_data_lock |= (1 << ch);
                        st->ts++;
                        ret = nvs_buf_push(indio_dev, st->buf, st->ts);
                        if (ret > 0)
@@ -1263,13 +1306,13 @@ static int nvs_write_raw(struct iio_dev *indio_dev,
        mutex_unlock(&indio_dev->mlock);
        if (*st->fn_dev->sts & NVS_STS_SPEW_MSG) {
                if (ret)
-                       dev_err(st->dev, "%s %s c=%d %d:%d->%d:%d ERR=%d\n",
-                               __func__, msg, chan->scan_index,
-                               old, old2, val, val2, ret);
+                       dev_err(st->dev, "%s %s %s c=%d %d:%d->%d:%d ERR=%d\n",
+                               __func__, st->cfg->name, msg,
+                               ch, old, old2, val, val2, ret);
                else
-                       dev_info(st->dev, "%s %s chan=%d %d:%d->%d:%d\n",
-                                __func__, msg, chan->scan_index,
-                                old, old2, val, val2);
+                       dev_info(st->dev, "%s %s %s chan=%d %d:%d->%d:%d\n",
+                                __func__, st->cfg->name, msg,
+                                ch, old, old2, val, val2);
        }
        return ret;
 }
@@ -1560,7 +1603,12 @@ static int nvs_remove(void *handle)
                devm_kfree(st->dev, st->ch);
        if (st->buf)
                devm_kfree(st->dev, st->buf);
-       dev_info(st->dev, "%s\n", __func__);
+       if (st->cfg->name)
+               dev_info(st->dev, "%s %s snsr_id=%d\n",
+                        __func__, st->cfg->name, st->cfg->snsr_id);
+       else
+               dev_info(st->dev, "%s snsr_id=%d\n",
+                        __func__, st->cfg->snsr_id);
        iio_device_free(indio_dev);
        return 0;
 }
@@ -1672,11 +1720,16 @@ static int nvs_probe(void **handle, void *dev_client, struct device *dev,
        }
 
        *handle = indio_dev;
-       dev_info(st->dev, "%s done\n", __func__);
+       dev_info(st->dev, "%s %s done\n", __func__, st->cfg->name);
        return 0;
 
 nvs_probe_err:
-       dev_err(st->dev, "%s ERR %d\n", __func__, ret);
+       if (st->cfg->name)
+               dev_err(st->dev, "%s %s snsr_id=%d EXIT ERR=%d\n",
+                       __func__, st->cfg->name, st->cfg->snsr_id, ret);
+       else
+               dev_err(st->dev, "%s snsr_id=%d EXIT ERR=%d\n",
+                       __func__, st->cfg->snsr_id, ret);
        nvs_remove(indio_dev);
        return ret;
 }
index 8231c66b8dcaf154d0f4a2531df4fb705cdce125..d879ee7efaa0bb463051752d720653b0ef719fb8 100644 (file)
@@ -40,8 +40,8 @@
 #define CM_LIGHT_SCALE_MICRO           (10000)
 #define CM_LIGHT_OFFSET_IVAL           (0)
 #define CM_LIGHT_OFFSET_MICRO          (0)
-#define CM_LIGHT_THRESHOLD_LO          (100)
-#define CM_LIGHT_THRESHOLD_HI          (100)
+#define CM_LIGHT_THRESHOLD_LO          (5)
+#define CM_LIGHT_THRESHOLD_HI          (5)
 #define CM_POLL_DLY_MS_MIN             (100)
 #define CM_POLL_DLY_MS_MAX             (4000)
 /* HW registers */
@@ -358,12 +358,19 @@ static int cm_regs(void *client, int snsr_id, char *buf)
        return t;
 }
 
+static int cm_dbg(void *client, int snsr_id, char *buf)
+{
+       struct cm_state *st = (struct cm_state *)client;
+       return nvs_light_dbg(&st->light, buf);
+}
+
 static struct nvs_fn_dev cm_fn_dev = {
        .enable                         = cm_enable,
        .batch                          = cm_batch,
        .thresh_lo                      = cm_thresh_lo,
        .thresh_hi                      = cm_thresh_hi,
        .regs                           = cm_regs,
+       .nvs_read                       = cm_dbg,
 };
 
 static int cm_suspend(struct device *dev)
@@ -472,6 +479,10 @@ static int cm_of_dt(struct cm_state *st, struct device_node *dn)
                st->light.nld_i_lo = 0;
                st->light.nld_i_hi = ARRAY_SIZE(cm_nld_tbl) - 1;
        }
+       if (st->light.nld_i_lo >= ARRAY_SIZE(cm_nld_tbl))
+               st->light.nld_i_lo = ARRAY_SIZE(cm_nld_tbl) - 1;
+       if (st->light.nld_i_hi >= ARRAY_SIZE(cm_nld_tbl))
+               st->light.nld_i_hi = ARRAY_SIZE(cm_nld_tbl) - 1;
        i = st->light.nld_i_lo;
        st->cfg.resolution.ival = cm_nld_tbl[i].resolution.ival;
        st->cfg.resolution.fval = cm_nld_tbl[i].resolution.fval;
index f51e13f7aba3004a354c8129da5b920fb13fc1e4..94b34458403f64998ed2cfe8870ac7380fa0dae3 100644 (file)
@@ -178,6 +178,11 @@ struct nvs_fn_dev {
  * @resolution: resolution value
  *
  * Returns 0 on success or a negative error code.
+ * If a value > 0 is returned then sensor_cfg->resolution is
+ * updated as described in the below note.  This allows drivers
+ * with multiple sensors to only have to implement the device
+ * specific function for certain sensors and allow the NVS
+ * layer to handle the others.
  *
  * Note that if not implemented, resolution changes will change
  * sensor_cfg->resolution.  If implemented, it is expected
@@ -193,6 +198,11 @@ struct nvs_fn_dev {
  * @max_range: max_range value
  *
  * Returns 0 on success or a negative error code.
+ * If a value > 0 is returned then sensor_cfg->max_range is
+ * updated as described in the below note.  This allows drivers
+ * with multiple sensors to only have to implement the device
+ * specific function for certain sensors and allow the NVS
+ * layer to handle the others.
  *
  * Note that if not implemented, max_range changes will change
  * sensor_cfg->max_range.  If implemented, it is expected
@@ -209,6 +219,11 @@ struct nvs_fn_dev {
  * @scale: scale value
  *
  * Returns 0 on success or a negative error code.
+ * If a value > 0 is returned then sensor_cfg->scale is updated
+ * as described in the below note.  This allows drivers with
+ * multiple sensors to only have to implement the device
+ * specific function for certain sensors and allow the NVS
+ * layer to handle the others.
  *
  * Note that if not implemented, scale changes will change
  * sensor_cfg->scale.  If implemented, it is expected
@@ -225,6 +240,11 @@ struct nvs_fn_dev {
  * @offset: offset value
  *
  * Returns 0 on success or a negative error code.
+ * If a value > 0 is returned then sensor_cfg->offset is updated
+ * as described in the below note.  This allows drivers with
+ * multiple sensors to only have to implement the device
+ * specific function for certain sensors and allow the NVS
+ * layer to handle the others.
  *
  * Note that if not implemented, offset changes will change
  * sensor_cfg->offset.  If implemented, it is expected
@@ -240,6 +260,11 @@ struct nvs_fn_dev {
  * @thresh_lo: low threshold value
  *
  * Returns 0 on success or a negative error code.
+ * If a value > 0 is returned then sensor_cfg->thresh_lo is
+ * updated as described in the below note.  This allows drivers
+ * with multiple sensors to only have to implement the device
+ * specific function for certain sensors and allow the NVS
+ * layer to handle the others.
  *
  * Note that if not implemented, thresh_lo changes will change
  * sensor_cfg->thresh_lo.  If implemented, it is expected
@@ -254,6 +279,11 @@ struct nvs_fn_dev {
  * @thresh_hi: high threshold value
  *
  * Returns 0 on success or a negative error code.
+ * If a value > 0 is returned then sensor_cfg->thresh_hi is
+ * updated as described in the below note.  This allows drivers
+ * with multiple sensors to only have to implement the device
+ * specific function for certain sensors and allow the NVS
+ * layer to handle the others.
  *
  * Note that if not implemented, thresh_hi changes will change
  * sensor_cfg->thresh_hi.  If implemented, it is expected