From nobody Sat Feb 7 18:29:10 2026 Received: from mail-ed1-f46.google.com (mail-ed1-f46.google.com [209.85.208.46]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 658AB357728 for ; Mon, 19 Jan 2026 10:04:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.46 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768817095; cv=none; b=in+fSjlxXSEh3MohPxGJJGF77YDTI5tLXkAinGYxoiNOo+6MdXOvWfM/mB2V7H/+iLeJibbIYy5lc2L2UB92BHsnmarN2BYGYiQpjUl0g4nGBbF+FELe6WxGIHxVa1sFP04ZcnUwFjMG6KTXLAMOT+2Xnzkc9PS1RSp8MOz66oc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768817095; c=relaxed/simple; bh=aBIjT8HJMfYZDveJouRj4sa520yQuhHwAmIb09eSjwY=; h=From:To:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=HavzCps1KjwkL7sohNunCDGf/t+mnifMO3oTqCrV0biovCHVrIDSNxL7iIp9RMXDaHxgfYZkp7xTWopPUFAD8pP54c9yg/B/MXDJ/OT5C/q6YI2AR/sBqkJmDoS0B0JVW1JD8joaJ6j2UxVyr+fibnyAWd/Rqj4TJHeIW6xsffA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=baylibre.com; spf=pass smtp.mailfrom=baylibre.com; dkim=pass (2048-bit key) header.d=baylibre-com.20230601.gappssmtp.com header.i=@baylibre-com.20230601.gappssmtp.com header.b=SICmyfT3; arc=none smtp.client-ip=209.85.208.46 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=baylibre.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=baylibre-com.20230601.gappssmtp.com header.i=@baylibre-com.20230601.gappssmtp.com header.b="SICmyfT3" Received: by mail-ed1-f46.google.com with SMTP id 4fb4d7f45d1cf-64d0d41404cso7252234a12.0 for ; Mon, 19 Jan 2026 02:04:53 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1768817092; x=1769421892; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=RHmHZviAuhOhpKSUpCtTa1iFHF2rU7EWwgoioRxdGwg=; b=SICmyfT3WauIeYm1hdDlDKFBVwruQTeOZTc4sKAiSViWpuzUvb53aUK/kcz/bEOaWo Ut/19UCLOJvScMS0EnqviVdD2T7O4v+dQnAtV1avg6uq7eo3fkUuCd5Gh8PMfHjHCD/1 dviBX9HJYAO1vBVoHMA1eXflAPJM7aBs/0F9OPYCsUrPDv8sLBEvik9DY6TpMJAyMx9s h33Jt5OCCptdk4hPE8IAIaJb3yao1stUUc3DB6uTewmw/8hcgSxCH3GBV+9+7+KtWBMo CQiLgQjrvAYDOS4LoH5PnYhwY6c+T+5RMSsMbOapY3h7OkOt0evQURosuxDpkUWuosZM ap1Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1768817092; x=1769421892; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=RHmHZviAuhOhpKSUpCtTa1iFHF2rU7EWwgoioRxdGwg=; b=xMw0L2dyCHBle5+l6X0vQwHv7OZRseJ1ep0r6tVv234KFRLRmXC+WH1YBAmEs8bb9L nZoDo1YCNU2CS6TveHsFZwNnJPIKYLGQ0XVB7lPxDMPciISn5Y6D12lUq2r6ob361oBu tyozpgHGaYj+Edl8wpZahdm6dzmO9LiZ2gDs/6l9KojqwwAptzHjiDBU2n1Bx+C8mHFJ cRNzLMXOzW6zzS7HcKSWC8fvOI8cNaGb58Ykey3rhKOISe6MY2DktdQm0iyttgU0akrb Cu9oCDVIZrMBdI6cSGFoFM/DzRfAPstbrNM8aLi1GMvYR9o1qNoZ340e7k8ScP68y9V4 jRWQ== X-Forwarded-Encrypted: i=1; AJvYcCU4pwOCW+n9YktDbdzE0QHvk0rXYUgstphF2wjvUw7uX5qLnd/8mcvNo0ix/1w23zLXEvVa316pvkqQq6o=@vger.kernel.org X-Gm-Message-State: AOJu0YxJj2SdSIHC17oaw8E2Rv0YUiO7K6E8eebwXX3+SGt9oH1F80xM PO9pBJBVvFyxs+wsuaNRZFIAM098PPqoOAHqolnCLS7xS6773gpMstQ37hUwnk7PXhs= X-Gm-Gg: AY/fxX4XfGJsms/BDPrMHdH0t1uH2Sf28KOYCctiGvlxRWo+DyHPXuITUcLE0FPMSSu dclO+AMBfeeW/NJirEHex2TVRfHaD4UPjp4kMyaqjgeNiNgBR3jXwVHfm7IP/ZrLppgqGgdTuFd LRvnqdx0DTcDLauQB5SRsgpB1StOeJ83XPPKum0QZpHufWaFrbnWTHO2rdkwy51yNFKrC0WyFEh RXiILKEUo6E1JHt4DoVFoz7LupjLpV3aH1Uf44j6QncsFapVHF5uLFu+gd2XYg/69ZgP/OSR4NA 5PTK67qVYJUbNf6gLApqlAy1yA19GehLXntShWNN9S6pKN73ORXaEP9E1KnqruPJgCsA1hM1psf i9yFWsZaPGB1Qk+nwMi/qxTIDU+YyzrsX/J1IzlH2Veu3jImpZsFcrwI= X-Received: by 2002:a17:907:6d27:b0:b73:7b97:5bfb with SMTP id a640c23a62f3a-b8792f79634mr963249466b.33.1768817091611; Mon, 19 Jan 2026 02:04:51 -0800 (PST) Received: from localhost ([151.37.196.5]) by smtp.gmail.com with ESMTPSA id 4fb4d7f45d1cf-65452cda145sm9797493a12.9.2026.01.19.02.04.51 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 19 Jan 2026 02:04:51 -0800 (PST) From: Francesco Lavra To: Lorenzo Bianconi , Jonathan Cameron , David Lechner , =?UTF-8?q?Nuno=20S=C3=A1?= , Andy Shevchenko , linux-iio@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v3 1/3] iio: imu: st_lsm6dsx: set FIFO ODR for accelerometer and gyroscope only Date: Mon, 19 Jan 2026 11:04:47 +0100 Message-Id: <20260119100449.1559624-2-flavra@baylibre.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20260119100449.1559624-1-flavra@baylibre.com> References: <20260119100449.1559624-1-flavra@baylibre.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=1747; i=flavra@baylibre.com; h=from:subject; bh=aBIjT8HJMfYZDveJouRj4sa520yQuhHwAmIb09eSjwY=; b=owEB7QES/pANAwAKAe3xO3POlDZfAcsmYgBpbgGowZOLCXnAHBgihNqEZpm9U7tlz7gxjSjf/ ONRRLt/DCKJAbMEAAEKAB0WIQSGV4VPlTvcox7DFObt8TtzzpQ2XwUCaW4BqAAKCRDt8TtzzpQ2 X4b3C/9T+3fo5duBrXG1i+844DEj+97f2r0YKyGOfC5Q9X4PFTJjMtq2tiFwKBZw6YyzuWtv9Rw kQkcCUphhHrbcMBtU2qf7dBNtvxTMnaQtkpVOG1jlknJy5+0gUVYsUOSElGhGqxp/e3PIuGDBOA xJNTKF2TH11yi5LxOtWGyKL5wFi5Qy4Qt85Yd+7f+gdy7K0p+yIxJH+y6a/56Oq3Eg6SypW9s/O BVyHqckVeDlAvI3q/qC6jVnH8tGvzQtxTkQS3kMcQRl5U++kQaPYnb8qOlW9A0GlyrCUtpoRF21 /rXaM/KVADCyY8mxNYzDXxUlJwFse84GHApTBAiGZzLkYA4HJcMewrVzerYsPsv9YWCS9B65STN Kvrku56MQY+Lt2RF1LGdckAaP8EnG+TzNfVA3KQQorJqAihhBhtmaV8Q2ng9lMBeMFZT0bvwy7C 7USbHep8CyMjfI2q4+6JVriI6+3SeV0lWv5+UY/nFeCufj+pJ84th+Zfa7VDpx2r6OWE8= X-Developer-Key: i=flavra@baylibre.com; a=openpgp; fpr=8657854F953BDCA31EC314E6EDF13B73CE94365F Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The st_lsm6dsx_set_fifo_odr() function, which is called when enabling and disabling the hardware FIFO, checks the contents of the hw->settings->batch array at index sensor->id, and then sets the current ODR value in sensor registers that depend on whether the register address is set in the above array element. This logic is valid for internal sensors only, i.e. the accelerometer and gyroscope; however, since commit c91c1c844ebd ("iio: imu: st_lsm6dsx: add i2c embedded controller support"), this function is called also when configuring the hardware FIFO for external sensors (i.e. sensors accessed through the sensor hub functionality), which can result in unrelated device registers being written. Add a check to the beginning of st_lsm6dsx_set_fifo_odr() so that it does not touch any registers unless it is called for internal sensors. Fixes: c91c1c844ebd ("iio: imu: st_lsm6dsx: add i2c embedded controller sup= port") Signed-off-by: Francesco Lavra --- drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c b/drivers/iio/i= mu/st_lsm6dsx/st_lsm6dsx_buffer.c index 55d877745575..1ee2fc5f5f1f 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c @@ -225,6 +225,10 @@ static int st_lsm6dsx_set_fifo_odr(struct st_lsm6dsx_s= ensor *sensor, const struct st_lsm6dsx_reg *batch_reg; u8 data; =20 + /* Only internal sensors have a FIFO ODR configuration register. */ + if (sensor->id >=3D ARRAY_SIZE(hw->settings->batch)) + return 0; + batch_reg =3D &hw->settings->batch[sensor->id]; if (batch_reg->addr) { int val; --=20 2.39.5 From nobody Sat Feb 7 18:29:10 2026 Received: from mail-ej1-f41.google.com (mail-ej1-f41.google.com [209.85.218.41]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D9DFA3596E8 for ; Mon, 19 Jan 2026 10:04:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.41 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768817097; cv=none; b=FkEotezIiXC3LcO4iKaQtF1oU6Rd1xwpWnwecxmGtYOUL+HYaf64I2FePYXDQhPNilsxvBp1prtW8gtcSnJzreckdfZFv5ve4PeQXj2mFwOrrTF38r9d/gZFbkqIGA1PirMP61cNd5Z7l5hmDQjQME6xbqF/JAnAACoHEholfpE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768817097; c=relaxed/simple; bh=MkM0A/HsyN7aXTv8muMJJ3kq/6hFQVpMJ9om7R8iWDM=; h=From:To:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=Vx0jss2BHMoHcMRdp1scyodPisJa6qyzmUxqvAFjwABGB3r9JYEeddIZqRYddzSfZBX3YOz3kIM+GnqtrgiXI3XV2KapXx3wktyzpJztTmVrQ5L4h7g/avo8l+X5JyjA8K2ErKqV5ezTtByh9DFOpIUWe3pMBga8HjhOS/IOoz0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=baylibre.com; spf=pass smtp.mailfrom=baylibre.com; dkim=pass (2048-bit key) header.d=baylibre-com.20230601.gappssmtp.com header.i=@baylibre-com.20230601.gappssmtp.com header.b=2JE4x0ZF; arc=none smtp.client-ip=209.85.218.41 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=baylibre.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=baylibre-com.20230601.gappssmtp.com header.i=@baylibre-com.20230601.gappssmtp.com header.b="2JE4x0ZF" Received: by mail-ej1-f41.google.com with SMTP id a640c23a62f3a-b87f3c684a1so4625866b.0 for ; Mon, 19 Jan 2026 02:04:54 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1768817093; x=1769421893; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=X2z+T2tcANuxuNpL/O66Pi5lTdKISXJnPtDtrt0skqs=; b=2JE4x0ZFFIF59kIBSF8mPvAv74Z2IzHmNVuV7afNvrhHDfuzYzvvW8QMCG5UlsEhHf bJL2g5IQ6nH1194PDd7Pfc8Vv7tpoasg5VgTxBbIyD/flWkmB+l5MtYc2dgmfHvSUvMp QLsjN/IAo9H9bQmeir3htoGttjVkR8A0bo6/mvAo8PiR0onEStVlr9SiVHq/ef+8x7+M m3EkzTn0I+3Eu6ENpWaNbJuUEyc0zzj9+LMaVfcybNesLx4h1vANmgwO7i1UhFEueiP5 Ydohiis6qpKbCzLFLe9IQkCa8km7/N77WVeBKb55ByaBU/IaLfriXveVuJnAjxmYEYLE 4n5g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1768817093; x=1769421893; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=X2z+T2tcANuxuNpL/O66Pi5lTdKISXJnPtDtrt0skqs=; b=Te1yzHRC9r5uy44Mw5nnL7A6lmvtZuw7riwsrLkBokyg1FIqNVILoHI/36wfpAvS+f Rsxnf7kaXh7buQ3rmNs/kvcUhtUHAUEjNLVkSb2L6XPHk3FRSUxC8LMLb+qbWymtsHA9 jTbvVsCBACosalv8l+FqyqUtbJOEzIcmi1sxZxNSZFeks6uerYvRPYh1rVYJY6PB40JB asAxou4TP/6sJ/t39l5LKQyMIxLjO81KzonK6cmRsYaenmdhTtwm9urvbwkXAYUNbN5/ zvW3p15aghwoJ/ztnBzLJB8Og2cg93UOOaSt2ZsmwRFS0RRtNDBxvt/46ZrRozornTvY RaRQ== X-Forwarded-Encrypted: i=1; AJvYcCUS7FKqerfxe0Pxwc2PyMC+giYW+6GAdhBuF0FyqQBWt3a8Qd0z7fIoMN+5lAlgMe7YOb9VY2o9Br/0oxs=@vger.kernel.org X-Gm-Message-State: AOJu0YxvHq/JfUgMOUD8/NxH/CJcLO/QwPia7AyAyY92avRFm/hIyaqB 39lhZgGsz+1y9z4FiPuGEotsiysG3GrpRWRdOx0iTucK8fnKeF5iA98poydE4jzXxFk= X-Gm-Gg: AY/fxX5L0DbfxTQm+GqF2iLugyAGMgBArKOf3FmodNcEJ/sydA+zcPKzW75oTLL1W9Y AxnAkJkna9d7wZqZk1kEhyPKUj++ZQvrWGKMzyrc+d90SG7PSPm7vYhxms7n5qDKMM3KIJ/luqI pwgsmSl8mG0JkjDSbFILAzz01BygRDG5xLK9t/im/Y6Ms7cEOMMFJCNE+tCHzV5CJdHHo7+2XwW yIzrQMF2jTMg7IVy1RN4lObbn6kjx63jgr507t9htqXDTo1Kfgm9JJQHr+jR9g6vqmLD7C9bl8u pfYjpGUxFpyzrHnC9VesfRyz1tSXXJpsW2VjKXC0y2LwXQpP5y8uBDnt6wyVOepgryPmJvw01zW QNl/1Gg0IzNnQlMbbwBcpDduiuZ6sJ1dm+gDZACuyIFcs+2SX2RQ7oDM= X-Received: by 2002:a17:906:7305:b0:b72:a899:169f with SMTP id a640c23a62f3a-b8792d6cf8amr1035219366b.4.1768817092791; Mon, 19 Jan 2026 02:04:52 -0800 (PST) Received: from localhost ([151.37.196.5]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-b8795169dd6sm1121075766b.27.2026.01.19.02.04.52 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 19 Jan 2026 02:04:52 -0800 (PST) From: Francesco Lavra To: Lorenzo Bianconi , Jonathan Cameron , David Lechner , =?UTF-8?q?Nuno=20S=C3=A1?= , Andy Shevchenko , linux-iio@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v3 2/3] iio: imu: st_lsm6dsx: set buffer sampling frequency for accelerometer only Date: Mon, 19 Jan 2026 11:04:48 +0100 Message-Id: <20260119100449.1559624-3-flavra@baylibre.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20260119100449.1559624-1-flavra@baylibre.com> References: <20260119100449.1559624-1-flavra@baylibre.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=2119; i=flavra@baylibre.com; h=from:subject; bh=MkM0A/HsyN7aXTv8muMJJ3kq/6hFQVpMJ9om7R8iWDM=; b=owEB7QES/pANAwAKAe3xO3POlDZfAcsmYgBpbgGpzekMRgLVMzJRzGAWVnmajJ5v55zV0IGmF GehD4DC7SWJAbMEAAEKAB0WIQSGV4VPlTvcox7DFObt8TtzzpQ2XwUCaW4BqQAKCRDt8TtzzpQ2 X8vODACCXUbvZQprbWo5N0TTH+AgAFSCd8P2nUdAUySttBuiD4x+6cjnSXKha2V2xdldqUez0oj BxY2QKviGb+B+L9KbczmjbbJBcRS+8tVk7G0+5xJfTOBzxIFP+4DNFNzVrgo8nindu+K4FJfrvA /FklhRA21ROu4tO4DdQYKUUMBIqQTimyX3tIGRJJEtfR0lDHwuBQfQkUSz0LvcT6jTne7nB2s3R PVTvYSRQ5cvHcMMs8hdVVas9AYz1fb/AKKnfX5Ay+QjBtu5clv6NhiZ5IwHbT9ButvQ5yH9XKBm Mk+oHVveCVIotqEqWsL1ldvt2wczWIyA591JlpgdjnP+81z2i6lZHGQpTrEi0DNLE/zoU6pp9j0 jhwdGPotfG1AOzmmW7oI9hYfrT3uWhPq1cl17uFgiBHCWY3vIRJw5Iy39lly4sn1TImPSfSWtoy CPy+/eJ+hujserj5uNrZztD+M6wWwzPv9+f+dlivEx13cWIPTzu61r04GSDkh+eTMIUrY= X-Developer-Key: i=flavra@baylibre.com; a=openpgp; fpr=8657854F953BDCA31EC314E6EDF13B73CE94365F Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The st_lsm6dsx_hwfifo_odr_store() function, which is called when userspace writes the buffer sampling frequency sysfs attribute, calls st_lsm6dsx_check_odr(), which accesses the odr_table array at index `sensor->id`; since this array is only 2 entries long, an access for any sensor type other than accelerometer or gyroscope is an out-of-bounds access. The motivation for being able to set a buffer frequency different from the sensor sampling frequency is to support use cases that need accurate event detection (which requires a high sampling frequency) while retrieving sensor data at low frequency. Since all the supported event types are generated from acceleration data only, do not create the buffer sampling frequency attribute for sensor types other than the accelerometer. Fixes: 6b648a36c200 ("iio: imu: st_lsm6dsx: Decouple sensor ODR from FIFO b= atch data rate") Signed-off-by: Francesco Lavra --- drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c b/drivers/iio/i= mu/st_lsm6dsx/st_lsm6dsx_buffer.c index 1ee2fc5f5f1f..5b28a3ffcc3d 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c @@ -862,12 +862,21 @@ int st_lsm6dsx_fifo_setup(struct st_lsm6dsx_hw *hw) int i, ret; =20 for (i =3D 0; i < ST_LSM6DSX_ID_MAX; i++) { + const struct iio_dev_attr **attrs; + if (!hw->iio_devs[i]) continue; =20 + /* + * For the accelerometer, allow setting FIFO sampling frequency + * values different from the sensor sampling frequency, which + * may be needed to keep FIFO data rate low while sampling + * acceleration data at high rates for accurate event detection. + */ + attrs =3D i =3D=3D ST_LSM6DSX_ID_ACC ? st_lsm6dsx_buffer_attrs : NULL; ret =3D devm_iio_kfifo_buffer_setup_ext(hw->dev, hw->iio_devs[i], &st_lsm6dsx_buffer_ops, - st_lsm6dsx_buffer_attrs); + attrs); if (ret) return ret; } --=20 2.39.5 From nobody Sat Feb 7 18:29:10 2026 Received: from mail-ej1-f50.google.com (mail-ej1-f50.google.com [209.85.218.50]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 573EF357737 for ; Mon, 19 Jan 2026 10:04:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.50 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768817098; cv=none; b=EnAu2m8G27Dy7yhtRpaKD505ueowc3Che9+bfkw9SPX42AyfN6Pio85kwu8tUG3X+AJy034eqZvMf1vUOCC7D3TQ6b44hMHHYaGgdvReVEKhlPJXMZ9G0jUTdcTmgpRl1PKMD5bULVVAJUAsk1zGSgMwxlh4Iggw9yNGrm00O+U= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768817098; c=relaxed/simple; bh=IdNDndd7w5r7M55hTueySne0XQOKVU9++ZeguJiIhU4=; h=From:To:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=m1PfmveDhSaNkDMTyFcc3zChrK5y3pnHqO0JYbxAx0OKi2oq+EEdIDdaEt0Y4HixzRx8tikE2J6n8eZQxXOCjJnBVhtO4CDcQTqOFSTXUvEC6GG1qtXXWcMVO8T50e77Ps1X5+yqITNI6TuQWzvnlBuJksJd83ARM6S/9TQbPAs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=baylibre.com; spf=pass smtp.mailfrom=baylibre.com; dkim=pass (2048-bit key) header.d=baylibre-com.20230601.gappssmtp.com header.i=@baylibre-com.20230601.gappssmtp.com header.b=Eyp0kUBW; arc=none smtp.client-ip=209.85.218.50 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=baylibre.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=baylibre-com.20230601.gappssmtp.com header.i=@baylibre-com.20230601.gappssmtp.com header.b="Eyp0kUBW" Received: by mail-ej1-f50.google.com with SMTP id a640c23a62f3a-b87f00ec06aso38695166b.1 for ; Mon, 19 Jan 2026 02:04:56 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1768817094; x=1769421894; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=TyWqUq5LW1GdDM0hxf7vaSFYPuU6ZgyjgP98+ub5RWo=; b=Eyp0kUBWFuh+84TTtiNP0QrRx9AihdwHyuLbInFgeuGnPH49jounPyBiDb6AB1uCDF 7xYNLvUlySEFHsDOHPp5LLXMWU5dYnfX3GJtqNw8pnpOq6wKV532CZszuJo8LHOtMCIc /hOpdJH3DpL1vQCvIVYKAH6T7OCZD5cplL5w3kE1ys/HcGkuWvvWj5zFz5PlChpLnZ5I ZVXVNuDuQq5djpPfvmxUwSduYSt/IERDelUsp9KN2k8tmcW3NWNDLk3kBuxhiCyHw+5r yjpNWTh6tl+9L5hqgeo/K8azMXbYkyOVNL0cp94YQGkcJjWIGrxw1S3cpeuw8iSMcOVu /bSw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1768817094; x=1769421894; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=TyWqUq5LW1GdDM0hxf7vaSFYPuU6ZgyjgP98+ub5RWo=; b=pi3mKnsOk+fF7AuupG1w12fyerl1HR3lP/hKpBsIhjI4i4e4K9swZPlb95rOevg3mi w2l426lvsyu7tQj1LTdC4tpsOyxG7pZvEmlNMChj3a1TPEnu7CmoeX0OBo/Vp4dqe+vq hpY8oO0NSzAPoe1bGdLzxcxXW26L8bLyenQV2sXgYzENrsdY9ddz2ME4AUUvdas1SD4T 6DStq9mZ6Z3b64h690b8CIZbz9Rm1wOvO4Bf3zcu4QLbNioGWqu3OhF+js2ioJKKO97Z DdgGy9WU33rNBBnS55Ga6+MzLzKUx0dbfMetgIjbQdgibVp/kG4QRjQdLZARW7ueMZ/i 8fqA== X-Forwarded-Encrypted: i=1; AJvYcCWPmt9NDQU5OzND3FiQy673WcmngqFF3OpatUs2tkfmo6lLu5X80qXLKMwj14E77w92VbpXwNuLhGVig/Y=@vger.kernel.org X-Gm-Message-State: AOJu0YxIzkZhsovpwtnkBRpwEnXFvuXJSfWUs9g0GJdXtA+KbASPdUjB XEBL2E8HALPCEr/dX73B4vKNYlcOFLPk3p0pm3grkaVda2gJgfxbnyuBgzX3XMMmwoQ= X-Gm-Gg: AY/fxX6mD9+NA7wFp1HIFbf3Z+4b6JHoyAcxV4/Nsh6X+nEtN0Nz7AekNqJGiz7Fx9R JlGtbA/f5mI/Gx+FWPZBMTQnnK2gA5XbJ7hXp7Abo6Yhiy53ikhvSE8pWY57ZANV0moSbLAXjGY darz3LKCbcemH9xsZ7BvTamGdLvQvVBKEZuxuw2jekRbxloTdkV/pU0V0k+sWK5Vblk8yC383nA tC0tiJFnwiwsLGyHf91Opazsyp97VBS4ZvH3RvUQH1yY7AF0ZJcNx5P9fZfe+dXuID0CvuWGKzF bptkYqhHCY32iJ7zw3M4nT0u0GcHg7x9f2XODLnNzGB3jdethGqOCuDr6lIKTGWaZCiGhmQF15Z V6a4O7UjvypcZsNvDO3gPxHTOoH0qP/+p7RqUdSm6G0JqTOAdDX/mY60= X-Received: by 2002:a17:907:a0c9:b0:b87:117f:b6f0 with SMTP id a640c23a62f3a-b8792fc4530mr1030605166b.30.1768817094330; Mon, 19 Jan 2026 02:04:54 -0800 (PST) Received: from localhost ([151.37.196.5]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-b87959c9fbbsm1082403666b.38.2026.01.19.02.04.53 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 19 Jan 2026 02:04:54 -0800 (PST) From: Francesco Lavra To: Lorenzo Bianconi , Jonathan Cameron , David Lechner , =?UTF-8?q?Nuno=20S=C3=A1?= , Andy Shevchenko , linux-iio@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v3 3/3] iio: imu: st_lsm6dsx: add support for rotation sensor Date: Mon, 19 Jan 2026 11:04:49 +0100 Message-Id: <20260119100449.1559624-4-flavra@baylibre.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20260119100449.1559624-1-flavra@baylibre.com> References: <20260119100449.1559624-1-flavra@baylibre.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=14868; i=flavra@baylibre.com; h=from:subject; bh=IdNDndd7w5r7M55hTueySne0XQOKVU9++ZeguJiIhU4=; b=owEB7QES/pANAwAKAe3xO3POlDZfAcsmYgBpbgGpuU6B8snJcX4r7ubTdSiorjIeBqeelyUFw v4q5XHYN6eJAbMEAAEKAB0WIQSGV4VPlTvcox7DFObt8TtzzpQ2XwUCaW4BqQAKCRDt8TtzzpQ2 XycmDACujL1uw6lOqo5udaxf+wgtFgaZq8c1hCEuLJ4457k22ZrdlUfxODCyPDdVwSPX/9YsZCN 4kOqWISUjEgel9cu65qyJ4mJnviH0oCBtvTmaoLm2EAgNjedtbvz0dCx7fL2UT/a9ygUAsfJRva IvVOsow0iPF8Dyj0RKU8ImQCsWklmopz5g9yI+ndvUhYZwOA/PDbre5OZQT8DvjwDU16x26mHPj 3Ix7D8qR2CwXniSHOUnlB3AG/6nVDOeP9OYfBIsfxgiav3ghaKyMn1W27nEVtDMdufGnmHgDVz9 rNUrA1gVvlked0Wl8//6SRYhA/VCBtUGcG43WuZ6VifuK74SQkn9EiekNrP6sfssmebkSzKS0e4 oJoLXHN2yQIj7UrSnTx6z3mSsUj2D/r/Bq+c+kOQoO2KLdHbfiwxtXyZulbZN3FEpTwhTMRbIA/ l29sW4PR3fnuc4rrZtOXIxC4RV2vnhmpE2WtZhuGplU8eVB8gztTL4qmLCP+5IMHxxhCY= X-Developer-Key: i=flavra@baylibre.com; a=openpgp; fpr=8657854F953BDCA31EC314E6EDF13B73CE94365F Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Some IMU chips in the LSM6DSX family have sensor fusion features that combine data from the accelerometer and gyroscope. One of these features generates rotation vector data and makes it available in the hardware FIFO as a quaternion (more specifically, the X, Y and Z components of the quaternion vector, expressed as 16-bit half-precision floating-point numbers). Add support for a new sensor instance that allows receiving sensor fusion data, by defining a new struct st_lsm6dsx_sf_settings (which contains chip-specific details for the sensor fusion functionality), and adding this struct as a new field in struct st_lsm6dsx_settings. In st_lsm6dsx_core.c, populate this new struct for the LSM6DSV and LSM6DSV16X chips, and add the logic to initialize an additional IIO device if this struct is populated for the hardware type being probed. Note: a new IIO device is being defined (as opposed to adding channels to an existing device) because the rate at which sensor fusion data is generated may not match the data rate from any of the existing devices. Tested on LSMDSV16X. Signed-off-by: Francesco Lavra Acked-by: Lorenzo Bianconi --- drivers/iio/imu/st_lsm6dsx/Makefile | 2 +- drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h | 26 ++- .../iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c | 16 +- drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c | 58 +++++ .../iio/imu/st_lsm6dsx/st_lsm6dsx_fusion.c | 220 ++++++++++++++++++ 5 files changed, 315 insertions(+), 7 deletions(-) create mode 100644 drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_fusion.c diff --git a/drivers/iio/imu/st_lsm6dsx/Makefile b/drivers/iio/imu/st_lsm6d= sx/Makefile index 57cbcd67d64f..19a488254de3 100644 --- a/drivers/iio/imu/st_lsm6dsx/Makefile +++ b/drivers/iio/imu/st_lsm6dsx/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-only st_lsm6dsx-y :=3D st_lsm6dsx_core.o st_lsm6dsx_buffer.o \ - st_lsm6dsx_shub.o + st_lsm6dsx_shub.o st_lsm6dsx_fusion.o =20 obj-$(CONFIG_IIO_ST_LSM6DSX) +=3D st_lsm6dsx.o obj-$(CONFIG_IIO_ST_LSM6DSX_I2C) +=3D st_lsm6dsx_i2c.o diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h b/drivers/iio/imu/st_l= sm6dsx/st_lsm6dsx.h index 07b1773c87bd..4173f670f7af 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h @@ -294,6 +294,7 @@ enum st_lsm6dsx_sensor_id { ST_LSM6DSX_ID_EXT0, ST_LSM6DSX_ID_EXT1, ST_LSM6DSX_ID_EXT2, + ST_LSM6DSX_ID_SF, ST_LSM6DSX_ID_MAX }; =20 @@ -301,6 +302,15 @@ enum st_lsm6dsx_ext_sensor_id { ST_LSM6DSX_ID_MAGN, }; =20 +struct st_lsm6dsx_sf_settings { + const struct iio_chan_spec *chan; + int chan_len; + struct st_lsm6dsx_odr_table_entry odr_table; + struct st_lsm6dsx_reg fifo_enable; + struct st_lsm6dsx_reg page_mux; + struct st_lsm6dsx_reg enable; +}; + /** * struct st_lsm6dsx_ext_dev_settings - i2c controller slave settings * @i2c_addr: I2c slave address list. @@ -388,6 +398,7 @@ struct st_lsm6dsx_settings { struct st_lsm6dsx_hw_ts_settings ts_settings; struct st_lsm6dsx_shub_settings shub_settings; struct st_lsm6dsx_event_settings event_settings; + struct st_lsm6dsx_sf_settings sf_settings; }; =20 enum st_lsm6dsx_fifo_mode { @@ -510,6 +521,9 @@ int st_lsm6dsx_check_odr(struct st_lsm6dsx_sensor *sens= or, u32 odr, u8 *val); int st_lsm6dsx_shub_probe(struct st_lsm6dsx_hw *hw, const char *name); int st_lsm6dsx_shub_set_enable(struct st_lsm6dsx_sensor *sensor, bool enab= le); int st_lsm6dsx_shub_read_output(struct st_lsm6dsx_hw *hw, u8 *data, int le= n); +int st_lsm6dsx_sf_probe(struct st_lsm6dsx_hw *hw, const char *name); +int st_lsm6dsx_sf_set_enable(struct st_lsm6dsx_sensor *sensor, bool enable= ); +int st_lsm6dsx_sf_set_odr(struct st_lsm6dsx_sensor *sensor, bool enable); int st_lsm6dsx_set_page(struct st_lsm6dsx_hw *hw, bool enable); =20 static inline int @@ -564,12 +578,14 @@ st_lsm6dsx_get_mount_matrix(const struct iio_dev *iio= _dev, static inline int st_lsm6dsx_device_set_enable(struct st_lsm6dsx_sensor *sensor, bool enable) { - if (sensor->id =3D=3D ST_LSM6DSX_ID_EXT0 || - sensor->id =3D=3D ST_LSM6DSX_ID_EXT1 || - sensor->id =3D=3D ST_LSM6DSX_ID_EXT2) + switch (sensor->id) { + case ST_LSM6DSX_ID_EXT0 ... ST_LSM6DSX_ID_EXT2: return st_lsm6dsx_shub_set_enable(sensor, enable); - - return st_lsm6dsx_sensor_set_enable(sensor, enable); + case ST_LSM6DSX_ID_SF: + return st_lsm6dsx_sf_set_enable(sensor, enable); + default: + return st_lsm6dsx_sensor_set_enable(sensor, enable); + } } =20 static const diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c b/drivers/iio/i= mu/st_lsm6dsx/st_lsm6dsx_buffer.c index 5b28a3ffcc3d..9a259e04755f 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c @@ -88,6 +88,7 @@ enum st_lsm6dsx_fifo_tag { ST_LSM6DSX_EXT0_TAG =3D 0x0f, ST_LSM6DSX_EXT1_TAG =3D 0x10, ST_LSM6DSX_EXT2_TAG =3D 0x11, + ST_LSM6DSX_ROT_TAG =3D 0x13, }; =20 static const @@ -226,8 +227,11 @@ static int st_lsm6dsx_set_fifo_odr(struct st_lsm6dsx_s= ensor *sensor, u8 data; =20 /* Only internal sensors have a FIFO ODR configuration register. */ - if (sensor->id >=3D ARRAY_SIZE(hw->settings->batch)) + if (sensor->id >=3D ARRAY_SIZE(hw->settings->batch)) { + if (sensor->id =3D=3D ST_LSM6DSX_ID_SF) + return st_lsm6dsx_sf_set_odr(sensor, enable); return 0; + } =20 batch_reg =3D &hw->settings->batch[sensor->id]; if (batch_reg->addr) { @@ -580,6 +584,16 @@ st_lsm6dsx_push_tagged_data(struct st_lsm6dsx_hw *hw, = u8 tag, case ST_LSM6DSX_EXT2_TAG: iio_dev =3D hw->iio_devs[ST_LSM6DSX_ID_EXT2]; break; + case ST_LSM6DSX_ROT_TAG: + /* + * The sensor reports only the {X, Y, Z} elements of the + * quaternion vector; set the W value to 0 (it can be derived + * from the {X, Y, Z} values due to the property that the vector + * is normalized). + */ + *(u16 *)(data + ST_LSM6DSX_SAMPLE_SIZE) =3D 0; + iio_dev =3D hw->iio_devs[ST_LSM6DSX_ID_SF]; + break; default: return -EINVAL; } diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c b/drivers/iio/imu= /st_lsm6dsx/st_lsm6dsx_core.c index dc0ae0e488ce..c21163a06a71 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c @@ -94,6 +94,24 @@ =20 #define ST_LSM6DSX_REG_WHOAMI_ADDR 0x0f =20 +/* Raw values from the IMU are 16-bit half-precision floating-point number= s. */ +#define ST_LSM6DSX_CHANNEL_ROT \ +{ \ + .type =3D IIO_ROT, \ + .modified =3D 1, \ + .channel2 =3D IIO_MOD_QUATERNION, \ + .info_mask_shared_by_all =3D BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .scan_index =3D 0, \ + .scan_type =3D { \ + .sign =3D 'u', \ + .realbits =3D 16, \ + .storagebits =3D 16, \ + .endianness =3D IIO_LE, \ + .repeat =3D 4, \ + }, \ + .ext_info =3D st_lsm6dsx_ext_info, \ +} + static const struct iio_event_spec st_lsm6dsx_ev_motion[] =3D { { .type =3D IIO_EV_TYPE_THRESH, @@ -153,6 +171,11 @@ static const struct iio_chan_spec st_lsm6ds0_gyro_chan= nels[] =3D { IIO_CHAN_SOFT_TIMESTAMP(3), }; =20 +static const struct iio_chan_spec st_lsm6dsx_sf_channels[] =3D { + ST_LSM6DSX_CHANNEL_ROT, + IIO_CHAN_SOFT_TIMESTAMP(1), +}; + static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] =3D { { .reset =3D { @@ -1492,6 +1515,35 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_s= ensor_settings[] =3D { }, }, }, + .sf_settings =3D { + .chan =3D st_lsm6dsx_sf_channels, + .chan_len =3D ARRAY_SIZE(st_lsm6dsx_sf_channels), + .odr_table =3D { + .reg =3D { + .addr =3D 0x5e, + .mask =3D GENMASK(5, 3), + }, + .odr_avl[0] =3D { 15000, 0x00 }, + .odr_avl[1] =3D { 30000, 0x01 }, + .odr_avl[2] =3D { 60000, 0x02 }, + .odr_avl[3] =3D { 120000, 0x03 }, + .odr_avl[4] =3D { 240000, 0x04 }, + .odr_avl[5] =3D { 480000, 0x05 }, + .odr_len =3D 6, + }, + .fifo_enable =3D { + .addr =3D 0x44, + .mask =3D BIT(1), + }, + .page_mux =3D { + .addr =3D 0x01, + .mask =3D BIT(7), + }, + .enable =3D { + .addr =3D 0x04, + .mask =3D BIT(1), + }, + }, }, { .reset =3D { @@ -2899,6 +2951,12 @@ int st_lsm6dsx_probe(struct device *dev, int irq, in= t hw_id, return err; } =20 + if (hw->settings->sf_settings.chan) { + err =3D st_lsm6dsx_sf_probe(hw, name); + if (err) + return err; + } + if (hw->irq > 0) { err =3D st_lsm6dsx_irq_setup(hw); if (err < 0) diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_fusion.c b/drivers/iio/i= mu/st_lsm6dsx/st_lsm6dsx_fusion.c new file mode 100644 index 000000000000..11ab246ef9d6 --- /dev/null +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_fusion.c @@ -0,0 +1,220 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * STMicroelectronics st_lsm6dsx IMU sensor fusion + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "st_lsm6dsx.h" + +static int +st_lsm6dsx_sf_get_odr_val(const struct st_lsm6dsx_sf_settings *settings, + u32 odr, u8 *val) +{ + int i; + + for (i =3D 0; i < settings->odr_table.odr_len; i++) { + if (settings->odr_table.odr_avl[i].milli_hz =3D=3D odr) + break; + } + if (i =3D=3D settings->odr_table.odr_len) + return -EINVAL; + + *val =3D settings->odr_table.odr_avl[i].val; + return 0; +} + +/** + * st_lsm6dsx_sf_set_page - Enable or disable access to sensor fusion + * configuration registers. + * @hw: Sensor hardware instance. + * @enable: True to enable access, false to disable access. + * + * Return: 0 on success, negative value on error. + */ +static int st_lsm6dsx_sf_set_page(struct st_lsm6dsx_hw *hw, bool enable) +{ + const struct st_lsm6dsx_reg *mux =3D &hw->settings->sf_settings.page_mux; + + return regmap_assign_bits(hw->regmap, mux->addr, mux->mask, enable); +} + +int st_lsm6dsx_sf_set_enable(struct st_lsm6dsx_sensor *sensor, bool enable) +{ + struct st_lsm6dsx_hw *hw =3D sensor->hw; + const struct st_lsm6dsx_reg *en_reg; + int err; + + guard(mutex)(&hw->page_lock); + + en_reg =3D &hw->settings->sf_settings.enable; + err =3D st_lsm6dsx_sf_set_page(hw, true); + if (err < 0) + return err; + + err =3D regmap_assign_bits(hw->regmap, en_reg->addr, en_reg->mask, enable= ); + if (err < 0) { + st_lsm6dsx_sf_set_page(hw, false); + return err; + } + + return st_lsm6dsx_sf_set_page(hw, false); +} + +int st_lsm6dsx_sf_set_odr(struct st_lsm6dsx_sensor *sensor, bool enable) +{ + struct st_lsm6dsx_hw *hw =3D sensor->hw; + const struct st_lsm6dsx_sf_settings *settings; + u8 data; + int err; + + guard(mutex)(&hw->page_lock); + + err =3D st_lsm6dsx_sf_set_page(hw, true); + if (err < 0) + return err; + + settings =3D &hw->settings->sf_settings; + if (enable) { + u8 odr_val; + const struct st_lsm6dsx_reg *reg =3D &settings->odr_table.reg; + + st_lsm6dsx_sf_get_odr_val(settings, sensor->hwfifo_odr_mHz, + &odr_val); + data =3D ST_LSM6DSX_SHIFT_VAL(odr_val, reg->mask); + err =3D regmap_update_bits(hw->regmap, reg->addr, reg->mask, + data); + if (err < 0) + goto out; + } + + err =3D regmap_assign_bits(hw->regmap, settings->fifo_enable.addr, + settings->fifo_enable.mask, enable); + if (err < 0) + goto out; + + return st_lsm6dsx_sf_set_page(hw, false); + +out: + st_lsm6dsx_sf_set_page(hw, false); + + return err; +} + +static int st_lsm6dsx_sf_read_raw(struct iio_dev *iio_dev, + struct iio_chan_spec const *ch, + int *val, int *val2, long mask) +{ + struct st_lsm6dsx_sensor *sensor =3D iio_priv(iio_dev); + + switch (mask) { + case IIO_CHAN_INFO_SAMP_FREQ: + *val =3D sensor->hwfifo_odr_mHz / MILLI; + *val2 =3D (sensor->hwfifo_odr_mHz % MILLI) * (MICRO / MILLI); + return IIO_VAL_INT_PLUS_MICRO; + default: + return -EINVAL; + } +} + +static int st_lsm6dsx_sf_write_raw(struct iio_dev *iio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + struct st_lsm6dsx_sensor *sensor =3D iio_priv(iio_dev); + const struct st_lsm6dsx_sf_settings *settings; + int err; + + settings =3D &sensor->hw->settings->sf_settings; + switch (mask) { + case IIO_CHAN_INFO_SAMP_FREQ: { + u32 odr_mHz =3D val * MILLI + val2 * MILLI / MICRO; + u8 odr_val; + + /* check that the requested frequency is supported */ + err =3D st_lsm6dsx_sf_get_odr_val(settings, odr_mHz, &odr_val); + if (err) + return err; + + sensor->hwfifo_odr_mHz =3D odr_mHz; + return 0; + } + default: + return -EINVAL; + } +} + +static ssize_t st_lsm6dsx_sf_sampling_freq_avail(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct st_lsm6dsx_sensor *sensor =3D iio_priv(dev_to_iio_dev(dev)); + const struct st_lsm6dsx_sf_settings *settings; + int len =3D 0; + + settings =3D &sensor->hw->settings->sf_settings; + for (unsigned int i =3D 0; i < settings->odr_table.odr_len; i++) { + u32 val =3D settings->odr_table.odr_avl[i].milli_hz; + + len +=3D sysfs_emit_at(buf, len, "%lu.%03lu ", val / MILLI, + val % MILLI); + } + buf[len - 1] =3D '\n'; + + return len; +} + +static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(st_lsm6dsx_sf_sampling_freq_avail); +static struct attribute *st_lsm6dsx_sf_attributes[] =3D { + &iio_dev_attr_sampling_frequency_available.dev_attr.attr, + NULL +}; + +static const struct attribute_group st_lsm6dsx_sf_attribute_group =3D { + .attrs =3D st_lsm6dsx_sf_attributes, +}; + +static const struct iio_info st_lsm6dsx_sf_info =3D { + .attrs =3D &st_lsm6dsx_sf_attribute_group, + .read_raw =3D st_lsm6dsx_sf_read_raw, + .write_raw =3D st_lsm6dsx_sf_write_raw, + .hwfifo_set_watermark =3D st_lsm6dsx_set_watermark, +}; + +int st_lsm6dsx_sf_probe(struct st_lsm6dsx_hw *hw, const char *name) +{ + const struct st_lsm6dsx_sf_settings *settings; + struct st_lsm6dsx_sensor *sensor; + struct iio_dev *iio_dev; + + iio_dev =3D devm_iio_device_alloc(hw->dev, sizeof(*sensor)); + if (!iio_dev) + return -ENOMEM; + + settings =3D &hw->settings->sf_settings; + sensor =3D iio_priv(iio_dev); + sensor->id =3D ST_LSM6DSX_ID_SF; + sensor->hw =3D hw; + sensor->hwfifo_odr_mHz =3D settings->odr_table.odr_avl[0].milli_hz; + sensor->watermark =3D 1; + iio_dev->modes =3D INDIO_DIRECT_MODE; + iio_dev->info =3D &st_lsm6dsx_sf_info; + iio_dev->channels =3D settings->chan; + iio_dev->num_channels =3D settings->chan_len; + snprintf(sensor->name, sizeof(sensor->name), "%s_sf", name); + iio_dev->name =3D sensor->name; + + /* + * Put the IIO device pointer in the iio_devs array so that the caller + * can set up a buffer and register this IIO device. + */ + hw->iio_devs[ST_LSM6DSX_ID_SF] =3D iio_dev; + + return 0; +} --=20 2.39.5