iio: cros_ec: Expose hwfifo_timeout
authorGwendal Grignou <gwendal@chromium.org>
Fri, 27 Mar 2020 22:34:40 +0000 (15:34 -0700)
committerEnric Balletbo i Serra <enric.balletbo@collabora.com>
Sat, 28 Mar 2020 21:04:33 +0000 (22:04 +0100)
Expose EC minimal interrupt period through buffer/hwfifo_timeout:
- Maximal timeout is limited to 65s.
- When timeout for all sensors is set to 0, EC will not send events,
  even if the sensor sampling rate is greater than 0.

Rename frequency to sampling_frequency to match IIO ABI.

Signed-off-by: Gwendal Grignou <gwendal@chromium.org>
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
drivers/iio/light/cros_ec_light_prox.c
drivers/iio/pressure/cros_ec_baro.c
include/linux/iio/common/cros_ec_sensors_core.h

index fad21a90bc7e8428fd512aaa177470e2c814d210..a66941fdb3855bea5fc1e45a7510d97e746b39d8 100644 (file)
@@ -236,6 +236,8 @@ static int cros_ec_sensors_probe(struct platform_device *pdev)
        if (ret)
                return ret;
 
+       iio_buffer_set_attrs(indio_dev->buffer, cros_ec_sensor_fifo_attributes);
+
        indio_dev->info = &ec_sensors_info;
        state = iio_priv(indio_dev);
        for (channel = state->channels, i = CROS_EC_SENSOR_X;
@@ -247,7 +249,6 @@ static int cros_ec_sensors_probe(struct platform_device *pdev)
                        BIT(IIO_CHAN_INFO_CALIBSCALE);
                channel->info_mask_shared_by_all =
                        BIT(IIO_CHAN_INFO_SCALE) |
-                       BIT(IIO_CHAN_INFO_FREQUENCY) |
                        BIT(IIO_CHAN_INFO_SAMP_FREQ);
                channel->info_mask_shared_by_all_available =
                        BIT(IIO_CHAN_INFO_SAMP_FREQ);
index a1ecbd55ea767300dcbb9c1470f86b21dc7f9dd2..b8eac7e5d5e5b4d39aa5611efd56537fe050b9b4 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/iio/common/cros_ec_sensors_core.h>
 #include <linux/iio/iio.h>
 #include <linux/iio/kfifo_buf.h>
+#include <linux/iio/sysfs.h>
 #include <linux/iio/trigger_consumer.h>
 #include <linux/iio/triggered_buffer.h>
 #include <linux/kernel.h>
@@ -83,6 +84,77 @@ static void get_default_min_max_freq(enum motionsensor_type type,
        }
 }
 
+static int cros_ec_sensor_set_ec_rate(struct cros_ec_sensors_core_state *st,
+                                     int rate)
+{
+       int ret;
+
+       if (rate > U16_MAX)
+               rate = U16_MAX;
+
+       mutex_lock(&st->cmd_lock);
+       st->param.cmd = MOTIONSENSE_CMD_EC_RATE;
+       st->param.ec_rate.data = rate;
+       ret = cros_ec_motion_send_host_cmd(st, 0);
+       mutex_unlock(&st->cmd_lock);
+       return ret;
+}
+
+static ssize_t cros_ec_sensor_set_report_latency(struct device *dev,
+                                                struct device_attribute *attr,
+                                                const char *buf, size_t len)
+{
+       struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+       struct cros_ec_sensors_core_state *st = iio_priv(indio_dev);
+       int integer, fract, ret;
+       int latency;
+
+       ret = iio_str_to_fixpoint(buf, 100000, &integer, &fract);
+       if (ret)
+               return ret;
+
+       /* EC rate is in ms. */
+       latency = integer * 1000 + fract / 1000;
+       ret = cros_ec_sensor_set_ec_rate(st, latency);
+       if (ret < 0)
+               return ret;
+
+       return len;
+}
+
+static ssize_t cros_ec_sensor_get_report_latency(struct device *dev,
+                                                struct device_attribute *attr,
+                                                char *buf)
+{
+       struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+       struct cros_ec_sensors_core_state *st = iio_priv(indio_dev);
+       int latency, ret;
+
+       mutex_lock(&st->cmd_lock);
+       st->param.cmd = MOTIONSENSE_CMD_EC_RATE;
+       st->param.ec_rate.data = EC_MOTION_SENSE_NO_VALUE;
+
+       ret = cros_ec_motion_send_host_cmd(st, 0);
+       latency = st->resp->ec_rate.ret;
+       mutex_unlock(&st->cmd_lock);
+       if (ret < 0)
+               return ret;
+
+       return sprintf(buf, "%d.%06u\n",
+                      latency / 1000,
+                      (latency % 1000) * 1000);
+}
+
+static IIO_DEVICE_ATTR(hwfifo_timeout, 0644,
+                      cros_ec_sensor_get_report_latency,
+                      cros_ec_sensor_set_report_latency, 0);
+
+const struct attribute *cros_ec_sensor_fifo_attributes[] = {
+       &iio_dev_attr_hwfifo_timeout.dev_attr.attr,
+       NULL,
+};
+EXPORT_SYMBOL_GPL(cros_ec_sensor_fifo_attributes);
+
 int cros_ec_sensors_push_data(struct iio_dev *indio_dev,
                              s16 *data,
                              s64 timestamp)
@@ -631,18 +703,6 @@ int cros_ec_sensors_core_read(struct cros_ec_sensors_core_state *st,
 
        switch (mask) {
        case IIO_CHAN_INFO_SAMP_FREQ:
-               st->param.cmd = MOTIONSENSE_CMD_EC_RATE;
-               st->param.ec_rate.data =
-                       EC_MOTION_SENSE_NO_VALUE;
-
-               ret = cros_ec_motion_send_host_cmd(st, 0);
-               if (ret)
-                       break;
-
-               *val = st->resp->ec_rate.ret;
-               ret = IIO_VAL_INT;
-               break;
-       case IIO_CHAN_INFO_FREQUENCY:
                st->param.cmd = MOTIONSENSE_CMD_SENSOR_ODR;
                st->param.sensor_odr.data =
                        EC_MOTION_SENSE_NO_VALUE;
@@ -712,7 +772,7 @@ int cros_ec_sensors_core_write(struct cros_ec_sensors_core_state *st,
        int ret;
 
        switch (mask) {
-       case IIO_CHAN_INFO_FREQUENCY:
+       case IIO_CHAN_INFO_SAMP_FREQ:
                st->param.cmd = MOTIONSENSE_CMD_SENSOR_ODR;
                st->param.sensor_odr.data = val;
 
@@ -721,15 +781,6 @@ int cros_ec_sensors_core_write(struct cros_ec_sensors_core_state *st,
 
                ret = cros_ec_motion_send_host_cmd(st, 0);
                break;
-       case IIO_CHAN_INFO_SAMP_FREQ:
-               st->param.cmd = MOTIONSENSE_CMD_EC_RATE;
-               st->param.ec_rate.data = val;
-
-               ret = cros_ec_motion_send_host_cmd(st, 0);
-               if (ret)
-                       break;
-               st->curr_sampl_freq = val;
-               break;
        default:
                ret = -EINVAL;
                break;
index e10b35de4c2fafffd6f20a9b2d137598915a0f81..2198b50909ed0de7159b62c187a0eb054aa199c3 100644 (file)
@@ -183,6 +183,8 @@ static int cros_ec_light_prox_probe(struct platform_device *pdev)
        if (ret)
                return ret;
 
+       iio_buffer_set_attrs(indio_dev->buffer, cros_ec_sensor_fifo_attributes);
+
        indio_dev->info = &cros_ec_light_prox_info;
        state = iio_priv(indio_dev);
        state->core.type = state->core.resp->info.type;
@@ -191,8 +193,7 @@ static int cros_ec_light_prox_probe(struct platform_device *pdev)
 
        /* Common part */
        channel->info_mask_shared_by_all =
-               BIT(IIO_CHAN_INFO_SAMP_FREQ) |
-               BIT(IIO_CHAN_INFO_FREQUENCY);
+               BIT(IIO_CHAN_INFO_SAMP_FREQ);
        channel->info_mask_shared_by_all_available =
                BIT(IIO_CHAN_INFO_SAMP_FREQ);
        channel->scan_type.realbits = CROS_EC_SENSOR_BITS;
index 6add499f11aa61abc5dc88ced5d6b35c78028fe6..c079b896008241e432cc9e70611a8d949722902b 100644 (file)
@@ -140,6 +140,8 @@ static int cros_ec_baro_probe(struct platform_device *pdev)
        if (ret)
                return ret;
 
+       iio_buffer_set_attrs(indio_dev->buffer, cros_ec_sensor_fifo_attributes);
+
        indio_dev->info = &cros_ec_baro_info;
        state = iio_priv(indio_dev);
        state->core.type = state->core.resp->info.type;
@@ -149,8 +151,7 @@ static int cros_ec_baro_probe(struct platform_device *pdev)
        channel->info_mask_separate = BIT(IIO_CHAN_INFO_RAW);
        channel->info_mask_shared_by_all =
                BIT(IIO_CHAN_INFO_SCALE) |
-               BIT(IIO_CHAN_INFO_SAMP_FREQ) |
-               BIT(IIO_CHAN_INFO_FREQUENCY);
+               BIT(IIO_CHAN_INFO_SAMP_FREQ);
        channel->info_mask_shared_by_all_available =
                BIT(IIO_CHAN_INFO_SAMP_FREQ);
        channel->scan_type.realbits = CROS_EC_SENSOR_BITS;
index 96ea4551945e2770dd7ab4bf403c7d6cfb6a20fa..5b0acc14c891f7de64584a2831a0fa05dcc42eac 100644 (file)
@@ -50,7 +50,6 @@ typedef irqreturn_t (*cros_ec_sensors_capture_t)(int irq, void *p);
  *                             the timestamp. The timestamp is always last and
  *                             is always 8-byte aligned.
  * @read_ec_sensors_data:      function used for accessing sensors values
- * @cuur_sampl_freq:           current sampling period
  */
 struct cros_ec_sensors_core_state {
        struct cros_ec_device *ec;
@@ -73,8 +72,6 @@ struct cros_ec_sensors_core_state {
        int (*read_ec_sensors_data)(struct iio_dev *indio_dev,
                                    unsigned long scan_mask, s16 *data);
 
-       int curr_sampl_freq;
-
        /* Table of known available frequencies : 0, Min and Max in mHz */
        int frequencies[3];
 };
@@ -116,5 +113,6 @@ int cros_ec_sensors_core_write(struct cros_ec_sensors_core_state *st,
 
 /* List of extended channel specification for all sensors */
 extern const struct iio_chan_spec_ext_info cros_ec_sensors_ext_info[];
+extern const struct attribute *cros_ec_sensor_fifo_attributes[];
 
 #endif  /* __CROS_EC_SENSORS_CORE_H */