[PATCH] iio: imu: inv_icm42600: Enable Pedometer Functionality

Hardevsinh Palaniya posted 1 patch 1 month, 1 week ago
drivers/iio/imu/inv_icm42600/inv_icm42600.h   |  16 ++
.../iio/imu/inv_icm42600/inv_icm42600_accel.c | 165 ++++++++++++++++++
.../iio/imu/inv_icm42600/inv_icm42600_core.c  |  36 +++-
3 files changed, 211 insertions(+), 6 deletions(-)
[PATCH] iio: imu: inv_icm42600: Enable Pedometer Functionality
Posted by Hardevsinh Palaniya 1 month, 1 week ago
Enables pedometer functionality in the ICM42605 IMU sensor.

The pedometer feature allows for step counting, which is accessible through
a new sysfs entry. Interrupts are triggered when a step event occurs, enabling
step event detection.

Signed-off-by: Hardevsinh Palaniya <hardevsinh.palaniya@siliconsignals.io>
---
 drivers/iio/imu/inv_icm42600/inv_icm42600.h   |  16 ++
 .../iio/imu/inv_icm42600/inv_icm42600_accel.c | 165 ++++++++++++++++++
 .../iio/imu/inv_icm42600/inv_icm42600_core.c  |  36 +++-
 3 files changed, 211 insertions(+), 6 deletions(-)

diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600.h b/drivers/iio/imu/inv_icm42600/inv_icm42600.h
index 3a07e43e4cf1..c3471b73152e 100644
--- a/drivers/iio/imu/inv_icm42600/inv_icm42600.h
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600.h
@@ -122,6 +122,7 @@ struct inv_icm42600_sensor_conf {
 	int filter;
 };
 #define INV_ICM42600_SENSOR_CONF_INIT		{-1, -1, -1, -1}
+#define INV_ICM42600_SENSOR_CONF_APEX		{ 2, 0, 9, 6}
 
 struct inv_icm42600_conf {
 	struct inv_icm42600_sensor_conf gyro;
@@ -141,6 +142,8 @@ struct inv_icm42600_suspended {
  *  @chip:		chip identifier.
  *  @name:		chip name.
  *  @map:		regmap pointer.
+ *  @pedometer_enable	status of pedometer function
+ *  @pedometer_value	status of steps event occurnce
  *  @vdd_supply:	VDD voltage regulator for the chip.
  *  @vddio_supply:	I/O voltage regulator for the chip.
  *  @orientation:	sensor chip orientation relative to main hardware.
@@ -157,6 +160,8 @@ struct inv_icm42600_state {
 	enum inv_icm42600_chip chip;
 	const char *name;
 	struct regmap *map;
+	bool pedometer_enable;
+	bool pedometer_value;
 	struct regulator *vdd_supply;
 	struct regulator *vddio_supply;
 	struct iio_mount_matrix orientation;
@@ -301,6 +306,15 @@ struct inv_icm42600_sensor_state {
 #define INV_ICM42600_GYRO_ACCEL_CONFIG0_GYRO_FILT(_f)	\
 		FIELD_PREP(GENMASK(3, 0), (_f))
 
+/* Pedometer functionality */
+#define INV_ICM42600_REG_APEX_CONFIG0                  0x0056
+#define INV_ICM42600_DMP_ODR_50Hz                      BIT(1)
+#define INV_ICM42600_PED_ENABLE                        BIT(5)
+#define INV_ICM42600_REG_INT_STATUS3                   0x0038
+#define INV_ICM42600_STEP_DET_INT                      BIT(5)
+#define INV_ICM42600_REG_APEX_DATA                     0x0031 // 2 Byte little-endian
+
+
 #define INV_ICM42600_REG_TMST_CONFIG			0x0054
 #define INV_ICM42600_TMST_CONFIG_MASK			GENMASK(4, 0)
 #define INV_ICM42600_TMST_CONFIG_TMST_TO_REGS_EN	BIT(4)
@@ -373,6 +387,8 @@ struct inv_icm42600_sensor_state {
 #define INV_ICM42600_INTF_CONFIG6_I3C_SDR_EN		BIT(0)
 
 /* User bank 4 (MSB 0x40) */
+#define INV_ICM42600_REG_INT_SOURCE6                    0x404D
+#define INV_ICM42600_STEP_DET_INT1_EN              	BIT(5)
 #define INV_ICM42600_REG_INT_SOURCE8			0x404F
 #define INV_ICM42600_INT_SOURCE8_FSYNC_IBI_EN		BIT(5)
 #define INV_ICM42600_INT_SOURCE8_PLL_RDY_IBI_EN		BIT(4)
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
index 56ac19814250..90fe4c9e15ab 100644
--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
@@ -160,6 +160,13 @@ static const struct iio_chan_spec_ext_info inv_icm42600_accel_ext_infos[] = {
 	{},
 };
 
+static const struct iio_event_spec icm42600_step_event = {
+	.type = IIO_EV_TYPE_CHANGE,
+	.dir = IIO_EV_DIR_NONE,
+	.mask_shared_by_type = BIT(IIO_EV_INFO_ENABLE) |
+	                       BIT(IIO_EV_INFO_VALUE),
+};
+
 static const struct iio_chan_spec inv_icm42600_accel_channels[] = {
 	INV_ICM42600_ACCEL_CHAN(IIO_MOD_X, INV_ICM42600_ACCEL_SCAN_X,
 				inv_icm42600_accel_ext_infos),
@@ -169,6 +176,14 @@ static const struct iio_chan_spec inv_icm42600_accel_channels[] = {
 				inv_icm42600_accel_ext_infos),
 	INV_ICM42600_TEMP_CHAN(INV_ICM42600_ACCEL_SCAN_TEMP),
 	IIO_CHAN_SOFT_TIMESTAMP(INV_ICM42600_ACCEL_SCAN_TIMESTAMP),
+	{
+	        .type = IIO_STEPS,
+	        .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
+	        .scan_index = -1,
+	        .event_spec = &icm42600_step_event,
+	        .num_event_specs = 1,
+	},
+
 };
 
 /*
@@ -668,6 +683,31 @@ static int inv_icm42600_accel_write_offset(struct inv_icm42600_state *st,
 	return ret;
 }
 
+static int inv_icm42600_steps_read_raw(struct iio_dev *indio_dev,
+                               struct iio_chan_spec const *chan,
+                               int *val, int *val2, long mask)
+{
+       struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
+       __le16 steps;
+       int ret;
+
+       if (mask == IIO_CHAN_INFO_PROCESSED) {
+               ret = iio_device_claim_direct_mode(indio_dev);
+               if (ret)
+                       return ret;
+               ret = regmap_bulk_read(st->map, INV_ICM42600_REG_APEX_DATA, &steps, sizeof(steps));
+               if (ret)
+                       return ret;
+               iio_device_release_direct_mode(indio_dev);
+               if (ret)
+                       return ret;
+               *val = steps;
+               return IIO_VAL_INT;
+       }
+
+       return -EINVAL;
+}
+
 static int inv_icm42600_accel_read_raw(struct iio_dev *indio_dev,
 				       struct iio_chan_spec const *chan,
 				       int *val, int *val2, long mask)
@@ -681,6 +721,8 @@ static int inv_icm42600_accel_read_raw(struct iio_dev *indio_dev,
 		break;
 	case IIO_TEMP:
 		return inv_icm42600_temp_read_raw(indio_dev, chan, val, val2, mask);
+	case IIO_STEPS:
+		return inv_icm42600_steps_read_raw(indio_dev, chan, val, val2, mask);
 	default:
 		return -EINVAL;
 	}
@@ -824,6 +866,126 @@ static int inv_icm42600_accel_hwfifo_flush(struct iio_dev *indio_dev,
 	return ret;
 }
 
+/*****************Pedometer Functionality**************/
+static int inv_icm42600_step_en(struct inv_icm42600_state *st, int state)
+{
+	struct inv_icm42600_sensor_conf conf = INV_ICM42600_SENSOR_CONF_APEX;
+	int ret, value;
+
+	if (state) {
+
+		ret = inv_icm42600_set_accel_conf(st, &conf, NULL);
+		if (ret)
+			return ret;
+
+		ret = regmap_write(st->map, INV_ICM42600_REG_APEX_CONFIG0,
+		                        INV_ICM42600_DMP_ODR_50Hz);
+		if (ret)
+			return ret;
+
+		ret = regmap_write(st->map, INV_ICM42600_REG_SIGNAL_PATH_RESET,
+		                        INV_ICM42600_SIGNAL_PATH_RESET_DMP_MEM_RESET);
+		if (ret)
+			return ret;
+		msleep(1);
+
+		ret = regmap_write(st->map, INV_ICM42600_REG_SIGNAL_PATH_RESET,
+		                        INV_ICM42600_SIGNAL_PATH_RESET_DMP_INIT_EN);
+		if (ret)
+			return ret;
+
+		ret = regmap_write(st->map, INV_ICM42600_REG_INT_SOURCE6,
+		                        INV_ICM42600_STEP_DET_INT1_EN);
+		if (ret)
+			return ret;
+
+		value = INV_ICM42600_DMP_ODR_50Hz | INV_ICM42600_PED_ENABLE;
+		ret = regmap_write(st->map, INV_ICM42600_REG_APEX_CONFIG0, value);
+		if (ret)
+			return ret;
+
+		st->pedometer_enable = true;
+
+	} else {
+
+		ret = regmap_write(st->map, INV_ICM42600_REG_APEX_CONFIG0, 0);
+		if (ret)
+			return ret;
+
+		ret = regmap_write(st->map, INV_ICM42600_REG_INT_SOURCE6, 0);
+		if (ret)
+			return ret;
+
+		st->pedometer_enable = false;
+	 }
+
+	return 0;
+}
+
+static int inv_icm42600_write_event_config(struct iio_dev *indio_dev,
+                                     const struct iio_chan_spec *chan,
+                                     enum iio_event_type type,
+                                     enum iio_event_direction dir, int state)
+{
+	struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
+	int ret;
+
+	if(chan->type != IIO_STEPS)
+	        return -EINVAL;
+
+	mutex_lock(&st->lock);
+
+	ret = inv_icm42600_step_en(st, state);
+
+	mutex_unlock(&st->lock);
+	return ret;
+}
+
+static int inv_icm42600_read_event_config(struct iio_dev *indio_dev,
+                                    const struct iio_chan_spec *chan,
+                                    enum iio_event_type type,
+                                    enum iio_event_direction dir)
+{
+	struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
+	int value;
+
+	if (chan->type != IIO_STEPS)
+	        return -EINVAL;
+
+	regmap_read(st->map, INV_ICM42600_REG_APEX_CONFIG0, &value);
+
+	if (value & INV_ICM42600_PED_ENABLE)
+	        return 1;
+	else
+	        return 0;
+}
+
+static int inv_icm42600_read_event_value(struct iio_dev *indio_dev,
+                                   const struct iio_chan_spec *chan,
+                                   enum iio_event_type type,
+                                   enum iio_event_direction dir,
+                                   enum iio_event_info info,
+                                   int *val, int *val2)
+{
+	struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
+
+	mutex_lock(&st->lock);
+
+	if (type == IIO_EV_TYPE_CHANGE) {
+		if (st->pedometer_value == true) {
+			*val = 1;
+		        st->pedometer_value = false;
+		} else {
+		        *val = 0;
+		}
+		mutex_unlock(&st->lock);
+		return IIO_VAL_INT;
+	}
+
+	mutex_unlock(&st->lock);
+	return -EINVAL;
+}
+
 static const struct iio_info inv_icm42600_accel_info = {
 	.read_raw = inv_icm42600_accel_read_raw,
 	.read_avail = inv_icm42600_accel_read_avail,
@@ -833,6 +995,9 @@ static const struct iio_info inv_icm42600_accel_info = {
 	.update_scan_mode = inv_icm42600_accel_update_scan_mode,
 	.hwfifo_set_watermark = inv_icm42600_accel_hwfifo_set_watermark,
 	.hwfifo_flush_to_buffer = inv_icm42600_accel_hwfifo_flush,
+	.write_event_config = inv_icm42600_write_event_config,
+	.read_event_config  = inv_icm42600_read_event_config,
+	.read_event_value   = inv_icm42600_read_event_value,
 };
 
 struct iio_dev *inv_icm42600_accel_init(struct inv_icm42600_state *st)
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c
index c3924cc6190e..4d78cb5ca396 100644
--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c
@@ -15,7 +15,8 @@
 #include <linux/pm_runtime.h>
 #include <linux/property.h>
 #include <linux/regmap.h>
-
+#include <linux/iio/events.h>
+#include <linux/of_irq.h>
 #include <linux/iio/iio.h>
 
 #include "inv_icm42600.h"
@@ -533,6 +534,19 @@ static irqreturn_t inv_icm42600_irq_handler(int irq, void *_data)
 
 	mutex_lock(&st->lock);
 
+	ret = regmap_read(st->map, INV_ICM42600_REG_INT_STATUS3, &status);
+	if (ret)
+	        goto out_unlock;
+
+	if (status & INV_ICM42600_STEP_DET_INT) {
+	        iio_push_event(st->indio_accel, IIO_MOD_EVENT_CODE(IIO_STEPS, 0,
+	                                                     IIO_NO_MOD,
+	                                                     IIO_EV_TYPE_CHANGE,
+	                                                     IIO_EV_DIR_NONE),
+	                                                        st->timestamp.accel);
+	        st->pedometer_value = true;
+	}
+
 	ret = regmap_read(st->map, INV_ICM42600_REG_INT_STATUS, &status);
 	if (ret)
 		goto out_unlock;
@@ -860,12 +876,20 @@ static int inv_icm42600_runtime_suspend(struct device *dev)
 	mutex_lock(&st->lock);
 
 	/* disable all sensors */
-	ret = inv_icm42600_set_pwr_mgmt0(st, INV_ICM42600_SENSOR_MODE_OFF,
-					 INV_ICM42600_SENSOR_MODE_OFF, false,
-					 NULL);
-	if (ret)
-		goto error_unlock;
+	if (st->pedometer_enable) {
+		ret = inv_icm42600_set_pwr_mgmt0(st, INV_ICM42600_SENSOR_MODE_OFF,
+						 INV_ICM42600_SENSOR_MODE_LOW_POWER,
+						false, NULL);
+		if (ret)
+			goto error_unlock;
+	} else {
 
+		ret = inv_icm42600_set_pwr_mgmt0(st, INV_ICM42600_SENSOR_MODE_OFF,
+						 INV_ICM42600_SENSOR_MODE_OFF,
+						 false, NULL);
+		if (ret)
+			goto error_unlock;
+	}
 	regulator_disable(st->vddio_supply);
 
 error_unlock:
-- 
2.43.0
Re: [PATCH] iio: imu: inv_icm42600: Enable Pedometer Functionality
Posted by Jonathan Cameron 1 month, 1 week ago
On Tue, 15 Oct 2024 14:50:03 +0530
Hardevsinh Palaniya <hardevsinh.palaniya@siliconsignals.io> wrote:

> Enables pedometer functionality in the ICM42605 IMU sensor.
> 
> The pedometer feature allows for step counting, which is accessible through
> a new sysfs entry. Interrupts are triggered when a step event occurs, enabling
> step event detection.
> 
> Signed-off-by: Hardevsinh Palaniya <hardevsinh.palaniya@siliconsignals.io>
Some additional comments from a quick read.

> ---
>  drivers/iio/imu/inv_icm42600/inv_icm42600.h   |  16 ++
>  .../iio/imu/inv_icm42600/inv_icm42600_accel.c | 165 ++++++++++++++++++
>  .../iio/imu/inv_icm42600/inv_icm42600_core.c  |  36 +++-
>  3 files changed, 211 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600.h b/drivers/iio/imu/inv_icm42600/inv_icm42600.h
> index 3a07e43e4cf1..c3471b73152e 100644
> --- a/drivers/iio/imu/inv_icm42600/inv_icm42600.h
> +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600.h
> @@ -122,6 +122,7 @@ struct inv_icm42600_sensor_conf {
>  	int filter;
>  };
>  #define INV_ICM42600_SENSOR_CONF_INIT		{-1, -1, -1, -1}
> +#define INV_ICM42600_SENSOR_CONF_APEX		{ 2, 0, 9, 6}
>  
>  struct inv_icm42600_conf {
>  	struct inv_icm42600_sensor_conf gyro;
> @@ -141,6 +142,8 @@ struct inv_icm42600_suspended {
>   *  @chip:		chip identifier.
>   *  @name:		chip name.
>   *  @map:		regmap pointer.
> + *  @pedometer_enable	status of pedometer function
> + *  @pedometer_value	status of steps event occurnce
Check the kernel-doc style.  Even better run the script over the
files you are touching.

You are missing : here.

>   *  @vdd_supply:	VDD voltage regulator for the chip.
>   *  @vddio_supply:	I/O voltage regulator for the chip.
>   *  @orientation:	sensor chip orientation relative to main hardware.
> @@ -157,6 +160,8 @@ struct inv_icm42600_state {
>  	enum inv_icm42600_chip chip;
>  	const char *name;
>  	struct regmap *map;
> +	bool pedometer_enable;
> +	bool pedometer_value;
>  	struct regulator *vdd_supply;
>  	struct regulator *vddio_supply;
>  	struct iio_mount_matrix orientation;
> @@ -301,6 +306,15 @@ struct inv_icm42600_sensor_state {
>  #define INV_ICM42600_GYRO_ACCEL_CONFIG0_GYRO_FILT(_f)	\
>  		FIELD_PREP(GENMASK(3, 0), (_f))
>  
> +/* Pedometer functionality */
> +#define INV_ICM42600_REG_APEX_CONFIG0                  0x0056
> +#define INV_ICM42600_DMP_ODR_50Hz                      BIT(1)
> +#define INV_ICM42600_PED_ENABLE                        BIT(5)
> +#define INV_ICM42600_REG_INT_STATUS3                   0x0038
> +#define INV_ICM42600_STEP_DET_INT                      BIT(5)
> +#define INV_ICM42600_REG_APEX_DATA                     0x0031 // 2 Byte little-endian

/* */ for comments in IIO (and most of the kernel)
Also, put it on the line above rather than making such a long line.
> +
one blank line is enough.
> +
>  #define INV_ICM42600_REG_TMST_CONFIG			0x0054
>  #define INV_ICM42600_TMST_CONFIG_MASK			GENMASK(4, 0)
>  #define INV_ICM42600_TMST_CONFIG_TMST_TO_REGS_EN	BIT(4)
> @@ -373,6 +387,8 @@ struct inv_icm42600_sensor_state {
>  #define INV_ICM42600_INTF_CONFIG6_I3C_SDR_EN		BIT(0)
>  
>  /* User bank 4 (MSB 0x40) */
> +#define INV_ICM42600_REG_INT_SOURCE6                    0x404D
> +#define INV_ICM42600_STEP_DET_INT1_EN              	BIT(5)
>  #define INV_ICM42600_REG_INT_SOURCE8			0x404F
>  #define INV_ICM42600_INT_SOURCE8_FSYNC_IBI_EN		BIT(5)
>  #define INV_ICM42600_INT_SOURCE8_PLL_RDY_IBI_EN		BIT(4)
> diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
> index 56ac19814250..90fe4c9e15ab 100644
> --- a/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
> +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
> @@ -160,6 +160,13 @@ static const struct iio_chan_spec_ext_info inv_icm42600_accel_ext_infos[] = {
>  	{},
>  };

> +static int inv_icm42600_steps_read_raw(struct iio_dev *indio_dev,
> +                               struct iio_chan_spec const *chan,
> +                               int *val, int *val2, long mask)
> +{
> +       struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
> +       __le16 steps;
> +       int ret;
> +
> +       if (mask == IIO_CHAN_INFO_PROCESSED) {
> +               ret = iio_device_claim_direct_mode(indio_dev);
> +               if (ret)
> +                       return ret;
> +               ret = regmap_bulk_read(st->map, INV_ICM42600_REG_APEX_DATA, &steps, sizeof(steps));
> +               if (ret)
> +                       return ret;
> +               iio_device_release_direct_mode(indio_dev);
> +               if (ret)
> +                       return ret;
> +               *val = steps;
As the bot pointed out, you need an endian conversion here.
le16_to_cpu()

> +               return IIO_VAL_INT;
> +       }
> +
> +       return -EINVAL;
> +}
> +
>  static int inv_icm42600_accel_read_raw(struct iio_dev *indio_dev,
>  				       struct iio_chan_spec const *chan,
>  				       int *val, int *val2, long mask)
> @@ -681,6 +721,8 @@ static int inv_icm42600_accel_read_raw(struct iio_dev *indio_dev,
>  		break;
>  	case IIO_TEMP:
>  		return inv_icm42600_temp_read_raw(indio_dev, chan, val, val2, mask);
> +	case IIO_STEPS:
> +		return inv_icm42600_steps_read_raw(indio_dev, chan, val, val2, mask);
>  	default:
>  		return -EINVAL;
>  	}
> @@ -824,6 +866,126 @@ static int inv_icm42600_accel_hwfifo_flush(struct iio_dev *indio_dev,
>  	return ret;
>  }
>  
> +/*****************Pedometer Functionality**************/

No to structure comments like this. They add little to readability and have
a habit of rapidly becoming wrong.

> +static int inv_icm42600_step_en(struct inv_icm42600_state *st, int state)
> +{
> +	struct inv_icm42600_sensor_conf conf = INV_ICM42600_SENSOR_CONF_APEX;
> +	int ret, value;
> +
> +	if (state) {
> +
> +		ret = inv_icm42600_set_accel_conf(st, &conf, NULL);
> +		if (ret)
> +			return ret;
> +
> +		ret = regmap_write(st->map, INV_ICM42600_REG_APEX_CONFIG0,
> +		                        INV_ICM42600_DMP_ODR_50Hz);
> +		if (ret)
> +			return ret;
> +
> +		ret = regmap_write(st->map, INV_ICM42600_REG_SIGNAL_PATH_RESET,
> +		                        INV_ICM42600_SIGNAL_PATH_RESET_DMP_MEM_RESET);
> +		if (ret)
> +			return ret;
> +		msleep(1);
Document the reason for this value.

> +
> +		ret = regmap_write(st->map, INV_ICM42600_REG_SIGNAL_PATH_RESET,
> +		                        INV_ICM42600_SIGNAL_PATH_RESET_DMP_INIT_EN);
> +		if (ret)
> +			return ret;
> +
> +		ret = regmap_write(st->map, INV_ICM42600_REG_INT_SOURCE6,
> +		                        INV_ICM42600_STEP_DET_INT1_EN);
> +		if (ret)
> +			return ret;
> +
> +		value = INV_ICM42600_DMP_ODR_50Hz | INV_ICM42600_PED_ENABLE;
> +		ret = regmap_write(st->map, INV_ICM42600_REG_APEX_CONFIG0, value);
> +		if (ret)
> +			return ret;
> +
> +		st->pedometer_enable = true;
	return here.
Then can drop the else.

With two such different paths, even better would be two little functions
to handle the two operations (enable + disable) as will make each individually
easier to read.
> +
> +	} else {
> +
> +		ret = regmap_write(st->map, INV_ICM42600_REG_APEX_CONFIG0, 0);
> +		if (ret)
> +			return ret;
> +
> +		ret = regmap_write(st->map, INV_ICM42600_REG_INT_SOURCE6, 0);
> +		if (ret)
> +			return ret;
> +
> +		st->pedometer_enable = false;
> +	 }
> +
> +	return 0;
> +}
> +
> +static int inv_icm42600_write_event_config(struct iio_dev *indio_dev,
> +                                     const struct iio_chan_spec *chan,
> +                                     enum iio_event_type type,
> +                                     enum iio_event_direction dir, int state)
> +{
> +	struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
> +	int ret;
> +
> +	if(chan->type != IIO_STEPS)
> +	        return -EINVAL;
> +
> +	mutex_lock(&st->lock);

guard() is useful in cases like this.

> +
> +	ret = inv_icm42600_step_en(st, state);
> +
> +	mutex_unlock(&st->lock);
> +	return ret;
> +}
> +
> +static int inv_icm42600_read_event_config(struct iio_dev *indio_dev,
> +                                    const struct iio_chan_spec *chan,
> +                                    enum iio_event_type type,
> +                                    enum iio_event_direction dir)
> +{
> +	struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
> +	int value;
> +
> +	if (chan->type != IIO_STEPS)
> +	        return -EINVAL;
> +
> +	regmap_read(st->map, INV_ICM42600_REG_APEX_CONFIG0, &value);
check return value.

> +
> +	if (value & INV_ICM42600_PED_ENABLE)
> +	        return 1;
> +	else
> +	        return 0;
> +}
> +
> +static int inv_icm42600_read_event_value(struct iio_dev *indio_dev,
This isn't to get if the event happened, it's for reading thresholds
etc. Not relevant for a pedometer.

> +                                   const struct iio_chan_spec *chan,
> +                                   enum iio_event_type type,
> +                                   enum iio_event_direction dir,
> +                                   enum iio_event_info info,
> +                                   int *val, int *val2)
> +{
> +	struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
> +
> +	mutex_lock(&st->lock);
guard()

> +
> +	if (type == IIO_EV_TYPE_CHANGE) {

flip logic and can test that before taking the lock

> +		if (st->pedometer_value == true) {
> +			*val = 1;
> +		        st->pedometer_value = false;
> +		} else {
> +		        *val = 0;
> +		}
> +		mutex_unlock(&st->lock);
> +		return IIO_VAL_INT;
> +	}
> +
> +	mutex_unlock(&st->lock);
> +	return -EINVAL;
> +}
> +
>  static const struct iio_info inv_icm42600_accel_info = {
>  	.read_raw = inv_icm42600_accel_read_raw,
>  	.read_avail = inv_icm42600_accel_read_avail,
> @@ -833,6 +995,9 @@ static const struct iio_info inv_icm42600_accel_info = {
>  	.update_scan_mode = inv_icm42600_accel_update_scan_mode,
>  	.hwfifo_set_watermark = inv_icm42600_accel_hwfifo_set_watermark,
>  	.hwfifo_flush_to_buffer = inv_icm42600_accel_hwfifo_flush,
> +	.write_event_config = inv_icm42600_write_event_config,
> +	.read_event_config  = inv_icm42600_read_event_config,
> +	.read_event_value   = inv_icm42600_read_event_value,
>  };
>  
>  struct iio_dev *inv_icm42600_accel_init(struct inv_icm42600_state *st)
> diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c
> index c3924cc6190e..4d78cb5ca396 100644
> --- a/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c
> +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c
> @@ -15,7 +15,8 @@
>  #include <linux/pm_runtime.h>
>  #include <linux/property.h>
>  #include <linux/regmap.h>
> -
Keep the blank line and keep the iio headers in their own section.

> +#include <linux/iio/events.h>
> +#include <linux/of_irq.h>
hmm. Can we not use the generic property accessors?
Also you aren't using any interrupt related new stuff in here so I think
this is just spurious.

>  #include <linux/iio/iio.h>
>  
>  #include "inv_icm42600.h"
> @@ -533,6 +534,19 @@ static irqreturn_t inv_icm42600_irq_handler(int irq, void *_data)
>  
>  	mutex_lock(&st->lock);
Probably worth considering use of guard() in here as a precursor patch.

>  
> +	ret = regmap_read(st->map, INV_ICM42600_REG_INT_STATUS3, &status);
> +	if (ret)
> +	        goto out_unlock;
> +
> +	if (status & INV_ICM42600_STEP_DET_INT) {
> +	        iio_push_event(st->indio_accel, IIO_MOD_EVENT_CODE(IIO_STEPS, 0,
> +	                                                     IIO_NO_MOD,
> +	                                                     IIO_EV_TYPE_CHANGE,
> +	                                                     IIO_EV_DIR_NONE),
> +	                                                        st->timestamp.accel);
> +	        st->pedometer_value = true;
> +	}
> +
>  	ret = regmap_read(st->map, INV_ICM42600_REG_INT_STATUS, &status);
>  	if (ret)
>  		goto out_unlock;
> @@ -860,12 +876,20 @@ static int inv_icm42600_runtime_suspend(struct device *dev)
>  	mutex_lock(&st->lock);
>  
>  	/* disable all sensors */
> -	ret = inv_icm42600_set_pwr_mgmt0(st, INV_ICM42600_SENSOR_MODE_OFF,
> -					 INV_ICM42600_SENSOR_MODE_OFF, false,
> -					 NULL);
> -	if (ret)
> -		goto error_unlock;
> +	if (st->pedometer_enable) {
> +		ret = inv_icm42600_set_pwr_mgmt0(st, INV_ICM42600_SENSOR_MODE_OFF,
> +						 INV_ICM42600_SENSOR_MODE_LOW_POWER,
> +						false, NULL);
> +		if (ret)
> +			goto error_unlock;
> +	} else {
>  
> +		ret = inv_icm42600_set_pwr_mgmt0(st, INV_ICM42600_SENSOR_MODE_OFF,
> +						 INV_ICM42600_SENSOR_MODE_OFF,
> +						 false, NULL);
> +		if (ret)
> +			goto error_unlock;
> +	}
>  	regulator_disable(st->vddio_supply);
>  
>  error_unlock:
Re: [PATCH] iio: imu: inv_icm42600: Enable Pedometer Functionality
Posted by kernel test robot 1 month, 1 week ago
Hi Hardevsinh,

kernel test robot noticed the following build warnings:

[auto build test WARNING on jic23-iio/togreg]
[also build test WARNING on linus/master v6.12-rc3 next-20241016]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Hardevsinh-Palaniya/iio-imu-inv_icm42600-Enable-Pedometer-Functionality/20241015-172227
base:   https://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio.git togreg
patch link:    https://lore.kernel.org/r/20241015092035.10482-1-hardevsinh.palaniya%40siliconsignals.io
patch subject: [PATCH] iio: imu: inv_icm42600: Enable Pedometer Functionality
config: i386-randconfig-062-20241016 (https://download.01.org/0day-ci/archive/20241016/202410161606.EbqeKmdm-lkp@intel.com/config)
compiler: gcc-12 (Debian 12.2.0-14) 12.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20241016/202410161606.EbqeKmdm-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202410161606.EbqeKmdm-lkp@intel.com/

sparse warnings: (new ones prefixed by >>)
>> drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c:704:21: sparse: sparse: incorrect type in assignment (different base types) @@     expected int @@     got restricted __le16 [addressable] [usertype] steps @@
   drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c:704:21: sparse:     expected int
   drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c:704:21: sparse:     got restricted __le16 [addressable] [usertype] steps

vim +704 drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c

   685	
   686	static int inv_icm42600_steps_read_raw(struct iio_dev *indio_dev,
   687	                               struct iio_chan_spec const *chan,
   688	                               int *val, int *val2, long mask)
   689	{
   690	       struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
   691	       __le16 steps;
   692	       int ret;
   693	
   694	       if (mask == IIO_CHAN_INFO_PROCESSED) {
   695	               ret = iio_device_claim_direct_mode(indio_dev);
   696	               if (ret)
   697	                       return ret;
   698	               ret = regmap_bulk_read(st->map, INV_ICM42600_REG_APEX_DATA, &steps, sizeof(steps));
   699	               if (ret)
   700	                       return ret;
   701	               iio_device_release_direct_mode(indio_dev);
   702	               if (ret)
   703	                       return ret;
 > 704	               *val = steps;
   705	               return IIO_VAL_INT;
   706	       }
   707	
   708	       return -EINVAL;
   709	}
   710	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki