From nobody Wed Oct 8 23:03:33 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D239124887D; Mon, 23 Jun 2025 12:56:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750683360; cv=none; b=o0eOVckCwInC+qFHWsx5QzxNSRhwoe8fod12OeoHAfEwp2HrDZIq+5pbxAd5rpVXTRF6w3ZUJsRlAtgUwfVdEe9a3Pdd+frFopCX0rzMJf+TGg0Vj+TkAV6UVvE73ioQ5mZLpgr2v9mfE9YWIFfqux2ZRaN4JFLUmPBkT3XJ9kc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750683360; c=relaxed/simple; bh=YuILsy/ohkvfKCdU2Ji92sX+6WIltRJpeKY8t27HCSw=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=ieyh+MVAoZfDhsyzc0NraqVOG4qYLDKNEGDQpMyhnicQbQpd0jpT2iLZGa1cQ2xYMSX9SpePofkIEYEROMRGr7ykJdzeqL79xKib7tAhARhfKNe46vOsN0WzVz+sHG4MhaJor8rsqjyiPIqMwRBqGnERBeSTUCIcw/yu+aWfO68= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=SqCn48LU; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="SqCn48LU" Received: by smtp.kernel.org (Postfix) with ESMTPS id 5F51CC4CEF0; Mon, 23 Jun 2025 12:56:00 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1750683360; bh=YuILsy/ohkvfKCdU2Ji92sX+6WIltRJpeKY8t27HCSw=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=SqCn48LU8XydkL/tHHPVsnA+EY30qKZU/V5FQZje4bzb8vpIUJj93F+3meZ7LMby+ YSD9yawW/b3tw/JFoQlEVvYd9ouy4jH5leXjneYoFg2sTvcVyG7ZFcU8RANyTYXbTR cO3FViX0vGer+zq9T8E0gnvLuG3XdLUCS/fbyX1hFrTDO4wbJuTz1CWZyDfhIlB4b2 wfJ/Z8bTYHz5Nm5QVZxzr3U7O3oxL7Z9fJQ6x+1c6U3zElKMXaaiBGpcG8ynEWh/D7 PURXG9H91Yo/mqhjjBQ9cNtzczURKyq/sSARP4c5k4ADItdWQxZOy7E6C5p63KcVTu /BTkxClBPD/VQ== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4DBCFC77B7F; Mon, 23 Jun 2025 12:56:00 +0000 (UTC) From: Jean-Baptiste Maneyrol via B4 Relay Date: Mon, 23 Jun 2025 14:55:52 +0200 Subject: [PATCH v5 1/3] iio: imu: inv_icm42600: move structure DMA buffers at the end Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250623-losd-3-inv-icm42600-add-wom-support-v5-1-4b3b33e028fe@tdk.com> References: <20250623-losd-3-inv-icm42600-add-wom-support-v5-0-4b3b33e028fe@tdk.com> In-Reply-To: <20250623-losd-3-inv-icm42600-add-wom-support-v5-0-4b3b33e028fe@tdk.com> To: Jonathan Cameron , Lars-Peter Clausen , David Lechner , =?utf-8?q?Nuno_S=C3=A1?= , Andy Shevchenko Cc: linux-iio@vger.kernel.org, linux-kernel@vger.kernel.org, Jean-Baptiste Maneyrol X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1750683359; l=1524; i=jean-baptiste.maneyrol@tdk.com; s=20240923; h=from:subject:message-id; bh=Sqk5EBW69Vb3qsTzZ8JKNX6MNPvlZeiK+pOwCYdRCz0=; b=yZ91Enn+j5euiJhL/kFfEZ/3Qeqk2J4+Olnz93SNdPg9C41wawcKrf802EsCcRbpCzlGeywD/ 2JNEJBVnaQbApO7CgYux8OdHV4MA7OM6sfUOYNITdEg1EUPujIfvaLq X-Developer-Key: i=jean-baptiste.maneyrol@tdk.com; a=ed25519; pk=bRqF1WYk0hR3qrnAithOLXSD0LvSu8DUd+quKLxCicI= X-Endpoint-Received: by B4 Relay for jean-baptiste.maneyrol@tdk.com/20240923 with auth_id=218 X-Original-From: Jean-Baptiste Maneyrol Reply-To: jean-baptiste.maneyrol@tdk.com From: Jean-Baptiste Maneyrol Move DMA buffers at the end of the structure to avoid overflow bugs with unexpected effect. struct inv_icm42600_fifo has a DMA buffer at the end. Signed-off-by: Jean-Baptiste Maneyrol --- drivers/iio/imu/inv_icm42600/inv_icm42600.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600.h b/drivers/iio/imu/= inv_icm42600/inv_icm42600.h index 55ed1ddaa8cb5dd410d17db3866fa0f22f18e9d2..9b2cce172670c5513f18d5979a5= ff563e9af4cb3 100644 --- a/drivers/iio/imu/inv_icm42600/inv_icm42600.h +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600.h @@ -148,9 +148,9 @@ struct inv_icm42600_suspended { * @suspended: suspended sensors configuration. * @indio_gyro: gyroscope IIO device. * @indio_accel: accelerometer IIO device. - * @buffer: data transfer buffer aligned for DMA. - * @fifo: FIFO management structure. * @timestamp: interrupt timestamps. + * @fifo: FIFO management structure. + * @buffer: data transfer buffer aligned for DMA. */ struct inv_icm42600_state { struct mutex lock; @@ -164,12 +164,12 @@ struct inv_icm42600_state { struct inv_icm42600_suspended suspended; struct iio_dev *indio_gyro; struct iio_dev *indio_accel; - u8 buffer[2] __aligned(IIO_DMA_MINALIGN); - struct inv_icm42600_fifo fifo; struct { s64 gyro; s64 accel; } timestamp; + struct inv_icm42600_fifo fifo; + u8 buffer[2] __aligned(IIO_DMA_MINALIGN); }; =20 =20 --=20 2.49.0 From nobody Wed Oct 8 23:03:33 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id F3FD4248F6E; Mon, 23 Jun 2025 12:56:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750683361; cv=none; b=A+9TdZZrxy2zpMtIr5FU2tMUGroyOLFIA6WCVg+uj1GG/vL/rT1fDaaOImde/pfibrwllrVcsuq0CVadjssxYxwYKqbYvos1rEaQrGXthO4VxS0leI26wpCTiF+CKVjWisVtfALVnoYr1dqj9DwRvcW2/AbrWiDKF00Mb9qPTrs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750683361; c=relaxed/simple; bh=Whjq55pmj4H+9Zis2WThKakgHmHVb4BahAExe7U4NWw=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=hsKXYEix46x+vy3Um30NtSxE+kIpskRc+6kzCovvabGCbYS360jdXPUWFMfjGq2YuHLEGkn79y9rGb2qzIUqFC760iMccJ3dOgvSvOLUbi2SKo8Z/HrzYhXWraGlVzdPCSdMn6TYv+dN8nsXiRalBHue0G9u4+dTVQgpTDL0bEo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=eHBViGwd; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="eHBViGwd" Received: by smtp.kernel.org (Postfix) with ESMTPS id 73A09C4AF09; Mon, 23 Jun 2025 12:56:00 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1750683360; bh=Whjq55pmj4H+9Zis2WThKakgHmHVb4BahAExe7U4NWw=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=eHBViGwdh+zDj7I3fX+7RBotaurhwgmYCRJXLjLtvl7+zDx/OTv+eCfwROtPO0/cJ 0z0wGmzgDiRA1zSbdyw8OSm+eWLK/Tm0O/OaUhjw58d2zdeqRz/wV2Cw8buBFbpCZM 5RXH4HHQcSAcAxmrZVUVIRvpFl2JC+Q0RTaBh1b/Wz7U5tn0d/isBFsh8oxq7SOfnV kAm9OM7R/q4KIrG9OILrgQw9GugYvtirMu435jHeNbUTSMPrHpPtE1Ya+hhKx5dCYH kqhDIpFd09c60bCTMJCGE7VJEhV26fuX2zm34cBr53AYFW03kjrEF3TKdPr8LLqkBu nQ/co9L4CZQAA== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5B8FEC7115B; Mon, 23 Jun 2025 12:56:00 +0000 (UTC) From: Jean-Baptiste Maneyrol via B4 Relay Date: Mon, 23 Jun 2025 14:55:53 +0200 Subject: [PATCH v5 2/3] iio: imu: inv_icm42600: add WoM support Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250623-losd-3-inv-icm42600-add-wom-support-v5-2-4b3b33e028fe@tdk.com> References: <20250623-losd-3-inv-icm42600-add-wom-support-v5-0-4b3b33e028fe@tdk.com> In-Reply-To: <20250623-losd-3-inv-icm42600-add-wom-support-v5-0-4b3b33e028fe@tdk.com> To: Jonathan Cameron , Lars-Peter Clausen , David Lechner , =?utf-8?q?Nuno_S=C3=A1?= , Andy Shevchenko Cc: linux-iio@vger.kernel.org, linux-kernel@vger.kernel.org, Jean-Baptiste Maneyrol X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1750683359; l=20125; i=jean-baptiste.maneyrol@tdk.com; s=20240923; h=from:subject:message-id; bh=uwhlsWej7xdBKMnLiJf/tZdkN9w+csem4CWmR4Flz1I=; b=Ju0A+bCZnUR7p1SeHHhnAejvmP6WceBM9HpHqZZocHJntEpax0PrnsztJ+ygaAGLLEwaJYgDl FIz90sOeFXUBxYHwx6J997gtnfoMI53dBmBnoHB+dYlwwwGNzZKAHJr X-Developer-Key: i=jean-baptiste.maneyrol@tdk.com; a=ed25519; pk=bRqF1WYk0hR3qrnAithOLXSD0LvSu8DUd+quKLxCicI= X-Endpoint-Received: by B4 Relay for jean-baptiste.maneyrol@tdk.com/20240923 with auth_id=218 X-Original-From: Jean-Baptiste Maneyrol Reply-To: jean-baptiste.maneyrol@tdk.com From: Jean-Baptiste Maneyrol Add WoM as accel roc rising x|y|z event. Signed-off-by: Jean-Baptiste Maneyrol --- drivers/iio/imu/inv_icm42600/inv_icm42600.h | 48 +++- drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c | 289 +++++++++++++++++= +++- drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.c | 2 +- drivers/iio/imu/inv_icm42600/inv_icm42600_core.c | 58 +++++ 4 files changed, 392 insertions(+), 5 deletions(-) diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600.h b/drivers/iio/imu/= inv_icm42600/inv_icm42600.h index 9b2cce172670c5513f18d5979a5ff563e9af4cb3..6af96df9f0ed195a211c40ca007= 5678f80b9424f 100644 --- a/drivers/iio/imu/inv_icm42600/inv_icm42600.h +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600.h @@ -135,6 +135,14 @@ struct inv_icm42600_suspended { bool temp; }; =20 +struct inv_icm42600_apex { + unsigned int on; + struct { + u64 value; + bool enable; + } wom; +}; + /** * struct inv_icm42600_state - driver state variables * @lock: lock for serializing multiple registers access. @@ -149,6 +157,7 @@ struct inv_icm42600_suspended { * @indio_gyro: gyroscope IIO device. * @indio_accel: accelerometer IIO device. * @timestamp: interrupt timestamps. + * @apex: APEX (Advanced Pedometer and Event detection) management * @fifo: FIFO management structure. * @buffer: data transfer buffer aligned for DMA. */ @@ -168,8 +177,9 @@ struct inv_icm42600_state { s64 gyro; s64 accel; } timestamp; + struct inv_icm42600_apex apex; struct inv_icm42600_fifo fifo; - u8 buffer[2] __aligned(IIO_DMA_MINALIGN); + u8 buffer[3] __aligned(IIO_DMA_MINALIGN); }; =20 =20 @@ -253,6 +263,18 @@ struct inv_icm42600_sensor_state { #define INV_ICM42600_REG_FIFO_COUNT 0x002E #define INV_ICM42600_REG_FIFO_DATA 0x0030 =20 +#define INV_ICM42600_REG_INT_STATUS2 0x0037 +#define INV_ICM42600_INT_STATUS2_SMD_INT BIT(3) +#define INV_ICM42600_INT_STATUS2_WOM_INT GENMASK(2, 0) + +#define INV_ICM42600_REG_INT_STATUS3 0x0038 +#define INV_ICM42600_INT_STATUS3_STEP_DET_INT BIT(5) +#define INV_ICM42600_INT_STATUS3_STEP_CNT_OVF_INT BIT(4) +#define INV_ICM42600_INT_STATUS3_TILT_DET_INT BIT(3) +#define INV_ICM42600_INT_STATUS3_WAKE_INT BIT(2) +#define INV_ICM42600_INT_STATUS3_SLEEP_INT BIT(1) +#define INV_ICM42600_INT_STATUS3_TAP_DET_INT BIT(0) + #define INV_ICM42600_REG_SIGNAL_PATH_RESET 0x004B #define INV_ICM42600_SIGNAL_PATH_RESET_DMP_INIT_EN BIT(6) #define INV_ICM42600_SIGNAL_PATH_RESET_DMP_MEM_RESET BIT(5) @@ -309,6 +331,14 @@ struct inv_icm42600_sensor_state { #define INV_ICM42600_TMST_CONFIG_TMST_FSYNC_EN BIT(1) #define INV_ICM42600_TMST_CONFIG_TMST_EN BIT(0) =20 +#define INV_ICM42600_REG_SMD_CONFIG 0x0057 +#define INV_ICM42600_SMD_CONFIG_WOM_INT_MODE BIT(3) +#define INV_ICM42600_SMD_CONFIG_WOM_MODE BIT(2) +#define INV_ICM42600_SMD_CONFIG_SMD_MODE_OFF 0x00 +#define INV_ICM42600_SMD_CONFIG_SMD_MODE_WOM 0x01 +#define INV_ICM42600_SMD_CONFIG_SMD_MODE_SHORT 0x02 +#define INV_ICM42600_SMD_CONFIG_SMD_MODE_LONG 0x03 + #define INV_ICM42600_REG_FIFO_CONFIG1 0x005F #define INV_ICM42600_FIFO_CONFIG1_RESUME_PARTIAL_RD BIT(6) #define INV_ICM42600_FIFO_CONFIG1_WM_GT_TH BIT(5) @@ -338,6 +368,11 @@ struct inv_icm42600_sensor_state { #define INV_ICM42600_INT_SOURCE0_FIFO_FULL_INT1_EN BIT(1) #define INV_ICM42600_INT_SOURCE0_UI_AGC_RDY_INT1_EN BIT(0) =20 +#define INV_ICM42600_REG_INT_SOURCE1 0x0066 +#define INV_ICM42600_INT_SOURCE1_I3C_ERROR_INT1_EN BIT(6) +#define INV_ICM42600_INT_SOURCE1_SMD_INT1_EN BIT(3) +#define INV_ICM42600_INT_SOURCE1_WOM_INT1_EN GENMASK(2, 0) + #define INV_ICM42600_REG_WHOAMI 0x0075 #define INV_ICM42600_WHOAMI_ICM42600 0x40 #define INV_ICM42600_WHOAMI_ICM42602 0x41 @@ -373,6 +408,10 @@ struct inv_icm42600_sensor_state { #define INV_ICM42600_INTF_CONFIG6_I3C_SDR_EN BIT(0) =20 /* User bank 4 (MSB 0x40) */ +#define INV_ICM42600_REG_ACCEL_WOM_X_THR 0x404A +#define INV_ICM42600_REG_ACCEL_WOM_Y_THR 0x404B +#define INV_ICM42600_REG_ACCEL_WOM_Z_THR 0x404C + #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) @@ -423,6 +462,9 @@ int inv_icm42600_set_gyro_conf(struct inv_icm42600_stat= e *st, int inv_icm42600_set_temp_conf(struct inv_icm42600_state *st, bool enable, unsigned int *sleep_ms); =20 +int inv_icm42600_enable_wom(struct inv_icm42600_state *st); +int inv_icm42600_disable_wom(struct inv_icm42600_state *st); + int inv_icm42600_debugfs_reg(struct iio_dev *indio_dev, unsigned int reg, unsigned int writeval, unsigned int *readval); =20 @@ -437,4 +479,8 @@ struct iio_dev *inv_icm42600_accel_init(struct inv_icm4= 2600_state *st); =20 int inv_icm42600_accel_parse_fifo(struct iio_dev *indio_dev); =20 +void inv_icm42600_accel_handle_events(struct iio_dev *indio_dev, + unsigned int status2, unsigned int status3, + s64 timestamp); + #endif diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c b/drivers/ii= o/imu/inv_icm42600/inv_icm42600_accel.c index 8a6f09e68f4934b406939a72f66486f408f43a21..0ac9378c62abe077ca21d7e68ca= 0fd94e3ece732 100644 --- a/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c @@ -10,9 +10,12 @@ #include #include #include +#include +#include =20 #include #include +#include #include #include =20 @@ -47,6 +50,16 @@ .ext_info =3D _ext_info, \ } =20 +#define INV_ICM42600_ACCEL_EVENT_CHAN(_modifier, _events, _events_nb) \ + { \ + .type =3D IIO_ACCEL, \ + .modified =3D 1, \ + .channel2 =3D _modifier, \ + .event_spec =3D _events, \ + .num_event_specs =3D _events_nb, \ + .scan_index =3D -1, \ + } + enum inv_icm42600_accel_scan { INV_ICM42600_ACCEL_SCAN_X, INV_ICM42600_ACCEL_SCAN_Y, @@ -82,14 +95,15 @@ static int inv_icm42600_accel_power_mode_set(struct iio= _dev *indio_dev, if (idx >=3D ARRAY_SIZE(inv_icm42600_accel_power_mode_values)) return -EINVAL; =20 - if (iio_buffer_enabled(indio_dev)) - return -EBUSY; - power_mode =3D inv_icm42600_accel_power_mode_values[idx]; filter =3D inv_icm42600_accel_filter_values[idx]; =20 guard(mutex)(&st->lock); =20 + /* cannot change if accel sensor is on */ + if (st->conf.accel.mode !=3D INV_ICM42600_SENSOR_MODE_OFF) + return -EBUSY; + /* prevent change if power mode is not supported by the ODR */ switch (power_mode) { case INV_ICM42600_SENSOR_MODE_LOW_NOISE: @@ -160,6 +174,16 @@ static const struct iio_chan_spec_ext_info inv_icm4260= 0_accel_ext_infos[] =3D { { } }; =20 +/* WoM event: rising ROC */ +static const struct iio_event_spec inv_icm42600_wom_events[] =3D { + { + .type =3D IIO_EV_TYPE_ROC, + .dir =3D IIO_EV_DIR_RISING, + .mask_separate =3D BIT(IIO_EV_INFO_ENABLE) | + BIT(IIO_EV_INFO_VALUE), + }, +}; + static const struct iio_chan_spec inv_icm42600_accel_channels[] =3D { INV_ICM42600_ACCEL_CHAN(IIO_MOD_X, INV_ICM42600_ACCEL_SCAN_X, inv_icm42600_accel_ext_infos), @@ -169,6 +193,8 @@ static const struct iio_chan_spec inv_icm42600_accel_ch= annels[] =3D { inv_icm42600_accel_ext_infos), INV_ICM42600_TEMP_CHAN(INV_ICM42600_ACCEL_SCAN_TEMP), IIO_CHAN_SOFT_TIMESTAMP(INV_ICM42600_ACCEL_SCAN_TIMESTAMP), + INV_ICM42600_ACCEL_EVENT_CHAN(IIO_MOD_X_OR_Y_OR_Z, inv_icm42600_wom_event= s, + ARRAY_SIZE(inv_icm42600_wom_events)), }; =20 /* @@ -294,6 +320,160 @@ static int inv_icm42600_accel_read_sensor(struct iio_= dev *indio_dev, return ret; } =20 +static unsigned int inv_icm42600_accel_convert_roc_to_wom(u64 roc, + int accel_hz, int accel_uhz) +{ + /* 1000/256mg per LSB converted in =C2=B5m/s=C2=B2 */ + const unsigned int convert =3D (9807U * (MICRO / MILLI)) / 256U; + u64 value; + u64 freq_uhz; + + /* return 0 only if roc is 0 */ + if (roc =3D=3D 0) + return 0; + + freq_uhz =3D (u64)accel_hz * MICRO + (u64)accel_uhz; + value =3D div64_u64(roc * MICRO, freq_uhz * (u64)convert); + + /* limit value to 8 bits and prevent 0 */ + return clamp(value, 1, 255); +} + +static u64 inv_icm42600_accel_convert_wom_to_roc(unsigned int threshold, + int accel_hz, int accel_uhz) +{ + /* 1000/256mg per LSB converted in =C2=B5m/s=C2=B2 */ + const unsigned int convert =3D (9807U * (MICRO / MILLI)) / 256U; + u64 value; + u64 freq_uhz; + + value =3D threshold * convert; + freq_uhz =3D (u64)accel_hz * MICRO + (u64)accel_uhz; + + /* compute the differential by multiplying by the frequency */ + return div_u64(value * freq_uhz, MICRO); +} + +static int inv_icm42600_accel_set_wom_threshold(struct inv_icm42600_state = *st, + u64 value, + int accel_hz, int accel_uhz) +{ + unsigned int threshold; + int ret; + + /* convert roc to wom threshold and convert back to handle clipping */ + threshold =3D inv_icm42600_accel_convert_roc_to_wom(value, accel_hz, acce= l_uhz); + value =3D inv_icm42600_accel_convert_wom_to_roc(threshold, accel_hz, acce= l_uhz); + + dev_dbg(regmap_get_device(st->map), "wom_threshold: 0x%x\n", threshold); + + /* set accel WoM threshold for the 3 axes */ + st->buffer[0] =3D threshold; + st->buffer[1] =3D threshold; + st->buffer[2] =3D threshold; + ret =3D regmap_bulk_write(st->map, INV_ICM42600_REG_ACCEL_WOM_X_THR, st->= buffer, 3); + if (ret) + return ret; + + st->apex.wom.value =3D value; + + return 0; +} + +static int inv_icm42600_accel_enable_wom(struct iio_dev *indio_dev) +{ + struct inv_icm42600_state *st =3D iio_device_get_drvdata(indio_dev); + struct inv_icm42600_sensor_state *accel_st =3D iio_priv(indio_dev); + struct device *pdev =3D regmap_get_device(st->map); + struct inv_icm42600_sensor_conf conf =3D INV_ICM42600_SENSOR_CONF_INIT; + unsigned int sleep_ms =3D 0; + int ret; + + ret =3D pm_runtime_resume_and_get(pdev); + if (ret) + return ret; + + scoped_guard(mutex, &st->lock) { + /* turn on accel sensor */ + conf.mode =3D accel_st->power_mode; + conf.filter =3D accel_st->filter; + ret =3D inv_icm42600_set_accel_conf(st, &conf, &sleep_ms); + } + if (ret) + goto error_suspend; + if (sleep_ms) + msleep(sleep_ms); + + scoped_guard(mutex, &st->lock) { + ret =3D inv_icm42600_enable_wom(st); + if (ret) + break; + st->apex.on++; + st->apex.wom.enable =3D true; + } + if (ret) + goto error_suspend; + + return 0; + +error_suspend: + pm_runtime_mark_last_busy(pdev); + pm_runtime_put_autosuspend(pdev); + return ret; +} + +static int inv_icm42600_accel_disable_wom(struct iio_dev *indio_dev) +{ + struct inv_icm42600_state *st =3D iio_device_get_drvdata(indio_dev); + struct device *pdev =3D regmap_get_device(st->map); + struct inv_icm42600_sensor_conf conf =3D INV_ICM42600_SENSOR_CONF_INIT; + unsigned int sleep_ms =3D 0; + int ret; + + scoped_guard(mutex, &st->lock) { + /* + * Consider that turning off WoM is always working to avoid + * blocking the chip in on mode and prevent going back to sleep. + * If there is an error, the chip will anyway go back to sleep + * and the feature will not work anymore. + */ + st->apex.wom.enable =3D false; + st->apex.on--; + ret =3D inv_icm42600_disable_wom(st); + if (ret) + break; + /* turn off accel sensor if not used */ + if (!st->apex.on && !iio_buffer_enabled(indio_dev)) { + conf.mode =3D INV_ICM42600_SENSOR_MODE_OFF; + ret =3D inv_icm42600_set_accel_conf(st, &conf, &sleep_ms); + if (ret) + break; + } + } + + if (sleep_ms) + msleep(sleep_ms); + pm_runtime_mark_last_busy(pdev); + pm_runtime_put_autosuspend(pdev); + + return ret; +} + +void inv_icm42600_accel_handle_events(struct iio_dev *indio_dev, + unsigned int status2, unsigned int status3, + s64 timestamp) +{ + struct inv_icm42600_state *st =3D iio_device_get_drvdata(indio_dev); + u64 ev_code; + + /* handle WoM event */ + if (st->apex.wom.enable && (status2 & INV_ICM42600_INT_STATUS2_WOM_INT)) { + ev_code =3D IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, IIO_MOD_X_OR_Y_OR_Z, + IIO_EV_TYPE_ROC, IIO_EV_DIR_RISING); + iio_push_event(indio_dev, ev_code, timestamp); + } +} + /* IIO format int + nano */ static const int inv_icm42600_accel_scale[] =3D { /* +/- 16G =3D> 0.004788403 m/s-2 */ @@ -464,6 +644,10 @@ static int inv_icm42600_accel_write_odr(struct iio_dev= *indio_dev, goto out_unlock; =20 ret =3D inv_icm42600_set_accel_conf(st, &conf, NULL); + if (ret) + goto out_unlock; + /* update wom threshold since roc is dependent on sampling frequency */ + ret =3D inv_icm42600_accel_set_wom_threshold(st, st->apex.wom.value, val,= val2); if (ret) goto out_unlock; inv_icm42600_buffer_update_fifo_period(st); @@ -819,6 +1003,101 @@ static int inv_icm42600_accel_hwfifo_flush(struct ii= o_dev *indio_dev, return ret; } =20 +static int inv_icm42600_accel_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 =3D iio_device_get_drvdata(indio_dev); + + /* handle only WoM (roc rising) event */ + if (type !=3D IIO_EV_TYPE_ROC || dir !=3D IIO_EV_DIR_RISING) + return -EINVAL; + + guard(mutex)(&st->lock); + + return st->apex.wom.enable ? 1 : 0; +} + +static int inv_icm42600_accel_write_event_config(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + bool state) +{ + struct inv_icm42600_state *st =3D iio_device_get_drvdata(indio_dev); + + /* handle only WoM (roc rising) event */ + if (type !=3D IIO_EV_TYPE_ROC || dir !=3D IIO_EV_DIR_RISING) + return -EINVAL; + + scoped_guard(mutex, &st->lock) { + if (st->apex.wom.enable =3D=3D state) + return 0; + } + + if (state) + return inv_icm42600_accel_enable_wom(indio_dev); + else + return inv_icm42600_accel_disable_wom(indio_dev); +} + +static int inv_icm42600_accel_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 =3D iio_device_get_drvdata(indio_dev); + u32 rem; + + /* handle only WoM (roc rising) event value */ + if (type !=3D IIO_EV_TYPE_ROC || dir !=3D IIO_EV_DIR_RISING) + return -EINVAL; + + guard(mutex)(&st->lock); + + /* return value in micro */ + *val =3D div_u64_rem(st->apex.wom.value, MICRO, &rem); + *val2 =3D rem; + return IIO_VAL_INT_PLUS_MICRO; +} + +static int inv_icm42600_accel_write_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 =3D iio_device_get_drvdata(indio_dev); + struct device *dev =3D regmap_get_device(st->map); + u64 value; + unsigned int accel_hz, accel_uhz; + int ret; + + /* handle only WoM (roc rising) event value */ + if (type !=3D IIO_EV_TYPE_ROC || dir !=3D IIO_EV_DIR_RISING) + return -EINVAL; + + if (val < 0 || val2 < 0) + return -EINVAL; + + value =3D (u64)val * MICRO + (u64)val2; + pm_runtime_get_sync(dev); + scoped_guard(mutex, &st->lock) { + ret =3D inv_icm42600_accel_read_odr(st, &accel_hz, &accel_uhz); + if (ret >=3D 0) + ret =3D inv_icm42600_accel_set_wom_threshold(st, value, + accel_hz, accel_uhz); + } + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); + + return ret; +} + static const struct iio_info inv_icm42600_accel_info =3D { .read_raw =3D inv_icm42600_accel_read_raw, .read_avail =3D inv_icm42600_accel_read_avail, @@ -828,6 +1107,10 @@ static const struct iio_info inv_icm42600_accel_info = =3D { .update_scan_mode =3D inv_icm42600_accel_update_scan_mode, .hwfifo_set_watermark =3D inv_icm42600_accel_hwfifo_set_watermark, .hwfifo_flush_to_buffer =3D inv_icm42600_accel_hwfifo_flush, + .read_event_config =3D inv_icm42600_accel_read_event_config, + .write_event_config =3D inv_icm42600_accel_write_event_config, + .read_event_value =3D inv_icm42600_accel_read_event_value, + .write_event_value =3D inv_icm42600_accel_write_event_value, }; =20 struct iio_dev *inv_icm42600_accel_init(struct inv_icm42600_state *st) diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.c b/drivers/i= io/imu/inv_icm42600/inv_icm42600_buffer.c index 00b9db52ca785589cedf1c90a857c2f420e18995..7c4ed981db043b4e8f3967b0802= 655d34f863954 100644 --- a/drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.c +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.c @@ -422,7 +422,7 @@ static int inv_icm42600_buffer_postdisable(struct iio_d= ev *indio_dev) conf.mode =3D INV_ICM42600_SENSOR_MODE_OFF; if (sensor =3D=3D INV_ICM42600_SENSOR_GYRO) ret =3D inv_icm42600_set_gyro_conf(st, &conf, &sleep_sensor); - else + else if (!st->apex.on) ret =3D inv_icm42600_set_accel_conf(st, &conf, &sleep_sensor); if (ret) goto out_unlock; diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c b/drivers/iio= /imu/inv_icm42600/inv_icm42600_core.c index a32236c78375df24697026cae1c924f7471af916..283483ed82ff42b4f9b80d99084= c118786054c37 100644 --- a/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c @@ -404,6 +404,37 @@ int inv_icm42600_set_temp_conf(struct inv_icm42600_sta= te *st, bool enable, sleep_ms); } =20 +int inv_icm42600_enable_wom(struct inv_icm42600_state *st) +{ + int ret; + + /* enable WoM hardware */ + ret =3D regmap_write(st->map, INV_ICM42600_REG_SMD_CONFIG, + INV_ICM42600_SMD_CONFIG_SMD_MODE_WOM | + INV_ICM42600_SMD_CONFIG_WOM_MODE); + if (ret) + return ret; + + /* enable WoM interrupt */ + return regmap_set_bits(st->map, INV_ICM42600_REG_INT_SOURCE1, + INV_ICM42600_INT_SOURCE1_WOM_INT1_EN); +} + +int inv_icm42600_disable_wom(struct inv_icm42600_state *st) +{ + int ret; + + /* disable WoM interrupt */ + ret =3D regmap_clear_bits(st->map, INV_ICM42600_REG_INT_SOURCE1, + INV_ICM42600_INT_SOURCE1_WOM_INT1_EN); + if (ret) + return ret; + + /* disable WoM hardware */ + return regmap_write(st->map, INV_ICM42600_REG_SMD_CONFIG, + INV_ICM42600_SMD_CONFIG_SMD_MODE_OFF); +} + int inv_icm42600_debugfs_reg(struct iio_dev *indio_dev, unsigned int reg, unsigned int writeval, unsigned int *readval) { @@ -548,6 +579,19 @@ static irqreturn_t inv_icm42600_irq_handler(int irq, v= oid *_data) =20 mutex_lock(&st->lock); =20 + if (st->apex.on) { + unsigned int status2, status3; + + /* read INT_STATUS2 and INT_STATUS3 in 1 operation */ + ret =3D regmap_bulk_read(st->map, INV_ICM42600_REG_INT_STATUS2, st->buff= er, 2); + if (ret) + goto out_unlock; + status2 =3D st->buffer[0]; + status3 =3D st->buffer[1]; + inv_icm42600_accel_handle_events(st->indio_accel, status2, status3, + st->timestamp.accel); + } + ret =3D regmap_read(st->map, INV_ICM42600_REG_INT_STATUS, &status); if (ret) goto out_unlock; @@ -819,6 +863,13 @@ static int inv_icm42600_suspend(struct device *dev) goto out_unlock; } =20 + /* disable APEX features */ + if (st->apex.wom.enable) { + ret =3D inv_icm42600_disable_wom(st); + if (ret) + goto out_unlock; + } + ret =3D inv_icm42600_set_pwr_mgmt0(st, INV_ICM42600_SENSOR_MODE_OFF, INV_ICM42600_SENSOR_MODE_OFF, false, NULL); @@ -860,6 +911,13 @@ static int inv_icm42600_resume(struct device *dev) if (ret) goto out_unlock; =20 + /* restore APEX features */ + if (st->apex.wom.enable) { + ret =3D inv_icm42600_enable_wom(st); + if (ret) + goto out_unlock; + } + /* restore FIFO data streaming */ if (st->fifo.on) { inv_sensors_timestamp_reset(&gyro_st->ts); --=20 2.49.0 From nobody Wed Oct 8 23:03:33 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D2324246BCA; Mon, 23 Jun 2025 12:56:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750683360; cv=none; b=uAdBET9OHKVIdxIzQAEYLyJZ1YNeHshCMvQo9I+ap3DLmRwlgwoBniOkYT0Bjc8Wycb4ENQ4xIBxA9drgGfK1B2vGzeLOI/RDiQi835qt80GDAq6jjR7Us7f1FB3r32ozWpPrVgAdQm3ZqqVNmGTwvcDFMHQyUGfQo8hGyePwtc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750683360; c=relaxed/simple; bh=lJ+ZJDw41L2YUh7IH+HIiLft7vpHiQokSehuD3PD1tE=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=O0kJ7rNgq6ZsSOzCyBTqAsT2EKAeMXAQUyeaMNkYSGD3VgiwwKj0cqgUKyq/Do0ONj2DidxJLoe6BW4d7QZ9m3nXihQSKEirFgvtV75gmvf62Kphd1DbJTeEfSrrPYmtIcIghUNLpquEid+M4wYVFtOHv1g7G3zSvLhx39QJjgU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=VkSYXqLy; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="VkSYXqLy" Received: by smtp.kernel.org (Postfix) with ESMTPS id 7720BC4CEF3; Mon, 23 Jun 2025 12:56:00 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1750683360; bh=lJ+ZJDw41L2YUh7IH+HIiLft7vpHiQokSehuD3PD1tE=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=VkSYXqLyqAvcYmCRk8mMSNhwekOj1pxZAzpvpZHVtRH+CdAtDIznwT2cwoJB2PBGk nmTyscPTWADbqS2lq5OmMCJJMYR4JXJSdRd5n6S96+gVHQKptxD0+FMso0vQzmlZi+ Z7fmAW4O9/L9ODbmcRRHVQEFnjyc5+wF2Cl+9f0+Ie+ilYtCIl1si5fxP1TpkVV8Az Igu1KQCqtHStOcdCfWbGi/txI08CPPtLodoDuWAhY2EuU9OjUhCfpV77s4TlrSU2Fd f6uBsE4EFjj9ujNMKs+a7VYVyxcHY2iaH5DOqoGS9H1pMEcCPXyba85ax/x8wOsyZC wJ6GyHKqRcs/A== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 68C3BC7EE31; Mon, 23 Jun 2025 12:56:00 +0000 (UTC) From: Jean-Baptiste Maneyrol via B4 Relay Date: Mon, 23 Jun 2025 14:55:54 +0200 Subject: [PATCH v5 3/3] iio: imu: inv_icm42600: add wakeup functionality for Wake-on-Motion Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250623-losd-3-inv-icm42600-add-wom-support-v5-3-4b3b33e028fe@tdk.com> References: <20250623-losd-3-inv-icm42600-add-wom-support-v5-0-4b3b33e028fe@tdk.com> In-Reply-To: <20250623-losd-3-inv-icm42600-add-wom-support-v5-0-4b3b33e028fe@tdk.com> To: Jonathan Cameron , Lars-Peter Clausen , David Lechner , =?utf-8?q?Nuno_S=C3=A1?= , Andy Shevchenko Cc: linux-iio@vger.kernel.org, linux-kernel@vger.kernel.org, Jean-Baptiste Maneyrol X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1750683359; l=5335; i=jean-baptiste.maneyrol@tdk.com; s=20240923; h=from:subject:message-id; bh=baN2V5WoQENBNBNGZ4kMSbhO+RDH8mGQ9jJN63y/PTw=; b=fI5ZLizu2ZrASjq6uFE3N4JVoGC8K78ezfXHU1//AruvEmEsJfH/fYxE2mFvVJH21QbTmPFrX luRmZSJCEg7BQ0XWtyg5o0iE5wxoVVASBBRgAitdjQ2sHTrlKqK0HbT X-Developer-Key: i=jean-baptiste.maneyrol@tdk.com; a=ed25519; pk=bRqF1WYk0hR3qrnAithOLXSD0LvSu8DUd+quKLxCicI= X-Endpoint-Received: by B4 Relay for jean-baptiste.maneyrol@tdk.com/20240923 with auth_id=218 X-Original-From: Jean-Baptiste Maneyrol Reply-To: jean-baptiste.maneyrol@tdk.com From: Jean-Baptiste Maneyrol When Wake-on-Motion is on, enable system wakeup and keep the chip on for waking up the system with an interrupt. Signed-off-by: Jean-Baptiste Maneyrol --- drivers/iio/imu/inv_icm42600/inv_icm42600.h | 2 + drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c | 5 +++ drivers/iio/imu/inv_icm42600/inv_icm42600_core.c | 53 +++++++++++++++++--= ---- 3 files changed, 47 insertions(+), 13 deletions(-) diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600.h b/drivers/iio/imu/= inv_icm42600/inv_icm42600.h index 6af96df9f0ed195a211c40ca0075678f80b9424f..1430ab4f1dea5d5ba6277d74275= fc44a6cd30eb8 100644 --- a/drivers/iio/imu/inv_icm42600/inv_icm42600.h +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600.h @@ -151,6 +151,7 @@ struct inv_icm42600_apex { * @map: regmap pointer. * @vdd_supply: VDD voltage regulator for the chip. * @vddio_supply: I/O voltage regulator for the chip. + * @irq: chip irq, required to enable/disable and set wakeup * @orientation: sensor chip orientation relative to main hardware. * @conf: chip sensors configurations. * @suspended: suspended sensors configuration. @@ -168,6 +169,7 @@ struct inv_icm42600_state { struct regmap *map; struct regulator *vdd_supply; struct regulator *vddio_supply; + int irq; struct iio_mount_matrix orientation; struct inv_icm42600_conf conf; struct inv_icm42600_suspended suspended; diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c b/drivers/ii= o/imu/inv_icm42600/inv_icm42600_accel.c index 0ac9378c62abe077ca21d7e68ca0fd94e3ece732..284e0e9f89e1b82090d121315fc= 744d3f9602dfe 100644 --- a/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c @@ -1171,6 +1171,11 @@ struct iio_dev *inv_icm42600_accel_init(struct inv_i= cm42600_state *st) if (ret) return ERR_PTR(ret); =20 + /* accel events are wakeup capable */ + ret =3D devm_device_init_wakeup(&indio_dev->dev); + if (ret) + return ERR_PTR(ret); + return indio_dev; } =20 diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c b/drivers/iio= /imu/inv_icm42600/inv_icm42600_core.c index 283483ed82ff42b4f9b80d99084c118786054c37..a4d42e7e21807f7954def431e9c= f03dffaa5bd5e 100644 --- a/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c @@ -765,6 +765,7 @@ int inv_icm42600_core_probe(struct regmap *regmap, int = chip, mutex_init(&st->lock); st->chip =3D chip; st->map =3D regmap; + st->irq =3D irq; =20 ret =3D iio_read_mount_matrix(dev, &st->orientation); if (ret) { @@ -843,6 +844,9 @@ EXPORT_SYMBOL_NS_GPL(inv_icm42600_core_probe, "IIO_ICM4= 2600"); static int inv_icm42600_suspend(struct device *dev) { struct inv_icm42600_state *st =3D dev_get_drvdata(dev); + struct device *accel_dev; + bool wakeup; + int accel_conf; int ret; =20 mutex_lock(&st->lock); @@ -863,20 +867,32 @@ static int inv_icm42600_suspend(struct device *dev) goto out_unlock; } =20 - /* disable APEX features */ - if (st->apex.wom.enable) { - ret =3D inv_icm42600_disable_wom(st); - if (ret) - goto out_unlock; + /* keep chip on and wake-up capable if APEX and wakeup on */ + accel_dev =3D &st->indio_accel->dev; + wakeup =3D st->apex.on && device_may_wakeup(accel_dev); + if (wakeup) { + /* keep accel on and setup irq for wakeup */ + accel_conf =3D st->conf.accel.mode; + enable_irq_wake(st->irq); + disable_irq(st->irq); + } else { + /* disable APEX features and accel if wakeup disabled */ + if (st->apex.wom.enable) { + ret =3D inv_icm42600_disable_wom(st); + if (ret) + goto out_unlock; + } + accel_conf =3D INV_ICM42600_SENSOR_MODE_OFF; } =20 ret =3D inv_icm42600_set_pwr_mgmt0(st, INV_ICM42600_SENSOR_MODE_OFF, - INV_ICM42600_SENSOR_MODE_OFF, false, - NULL); + accel_conf, false, NULL); if (ret) goto out_unlock; =20 - regulator_disable(st->vddio_supply); + /* disable vddio regulator if chip is sleeping */ + if (!wakeup) + regulator_disable(st->vddio_supply); =20 out_unlock: mutex_unlock(&st->lock); @@ -892,13 +908,24 @@ static int inv_icm42600_resume(struct device *dev) struct inv_icm42600_state *st =3D dev_get_drvdata(dev); struct inv_icm42600_sensor_state *gyro_st =3D iio_priv(st->indio_gyro); struct inv_icm42600_sensor_state *accel_st =3D iio_priv(st->indio_accel); + struct device *accel_dev; + bool wakeup; int ret; =20 mutex_lock(&st->lock); =20 - ret =3D inv_icm42600_enable_regulator_vddio(st); - if (ret) - goto out_unlock; + /* check wakeup capability */ + accel_dev =3D &st->indio_accel->dev; + wakeup =3D st->apex.on && device_may_wakeup(accel_dev); + /* restore irq state or vddio if cut off */ + if (wakeup) { + enable_irq(st->irq); + disable_irq_wake(st->irq); + } else { + ret =3D inv_icm42600_enable_regulator_vddio(st); + if (ret) + goto out_unlock; + } =20 pm_runtime_disable(dev); pm_runtime_set_active(dev); @@ -911,8 +938,8 @@ static int inv_icm42600_resume(struct device *dev) if (ret) goto out_unlock; =20 - /* restore APEX features */ - if (st->apex.wom.enable) { + /* restore APEX features if disabled */ + if (!wakeup && st->apex.wom.enable) { ret =3D inv_icm42600_enable_wom(st); if (ret) goto out_unlock; --=20 2.49.0