From nobody Sun Feb 8 05:35:30 2026 Received: from mail-ed1-f53.google.com (mail-ed1-f53.google.com [209.85.208.53]) (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 0F2E6394469 for ; Thu, 15 Jan 2026 12:24:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.53 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768479879; cv=none; b=X4jSqWcB+7CMU4eRIQ7Wg2hiVJ41qBsIGcFh1fxhiXp0jgW6Hs4uBKnjf+DAvHMjMGElbToT040dE7mPn+/IlKuM/8U+m+vyQv217Z7xDVjY2n3LJjAnbVfrjKnfARbY93dU9shlDzBJsBF95B8zc43+HhZogBPmnqQ/ZMOUYvU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768479879; c=relaxed/simple; bh=aBIjT8HJMfYZDveJouRj4sa520yQuhHwAmIb09eSjwY=; h=From:To:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=P5sr0Mh0AjV6BuSttk+Y/a43XfIpMP3kIDSy0+kS5z4QxSrOiNn74QSJu4exTlUerKIPnwE3mWgG1e/H0pyoYmtaZ2Y13mHz30h9J6kDlXiW+1G2gw2XA5HgezXBz3PZt0+SRH2NHzmZaomp0x0JkicO5NreYapPU/jdYqhyBKg= 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=sAsBEtxj; arc=none smtp.client-ip=209.85.208.53 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="sAsBEtxj" Received: by mail-ed1-f53.google.com with SMTP id 4fb4d7f45d1cf-64b9d01e473so1502318a12.2 for ; Thu, 15 Jan 2026 04:24:36 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1768479875; x=1769084675; 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=sAsBEtxjry09WtdDoDxsfmtDAFn6srXYSCIuOdt4eci7xEoiRLZ9GP4zch1VobcB0G 9q7bVYfHT6um35uVosex/ppf1++4WakbHSqjE9kvwjQKWpBCPoCUumpf1425ZK65UFSy gQhK6l+YPYp2aNJ2ri+hqOchu9T8KfozfddFlR5qcDGcisvwHfYIHzmtKx8/gD0aDwX/ EW9TeScHNy0yXbp7vrllSwikoKkGuJslDUQfXoWs1nX5ep0ze/cijoTV/q4yAWEiUdEm bMT6KUrJ0eXl5Ws+6TqkKcGql3ilCCRKJIzrBcO6MpHteBrkaFXVSNRYnRB4tS0dZ/1j MxGQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1768479875; x=1769084675; 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=a7X7o9vI9K6qAvphOaZg359h/YZFdsVcEIIE3z8X9KnQZcm/0iVoD7x+5PXEgYn7xU YFT30wOxa5Q6jMSDyws6ZB/tL25Y3uQ5jQ9OQuoh9Ww9/n/dJwaJ8W547tLw/QOMWt0T YPCLwYvVHV5yy0YWqS7Li0MyRHNyzZ0nViWMk1SOMk0rIlPkYeUEMcvZoNQK2RFvLI6i LajBiPjstXZx4cYE9vdf41g6EBDblrRm4PYcLPXcSaBQSKQwXK0VhcWhyDJqkyPGMg+6 71DRBLomQJryhwkU3aGJTaGREoWNP0rvRHMAE2lFk//52e1OXSonOIFIq69zbFzmdlSo jmaw== X-Forwarded-Encrypted: i=1; AJvYcCUJ1aFYkPHJRd7r1FSLalW3OiGXaH3Ai6AvZEWvjBi799vg/dSTzUWfv4Cb7GpjT8zW/GafGToLSZ31J/M=@vger.kernel.org X-Gm-Message-State: AOJu0Yz7uwfvj8+j/LaKc3Zjd+Qq8k4mmg9YjPy5Xw0DEdmQ+zSSzdPo BNGC7cRxiK1QegIHtbtVs0yuIPHyRq7XmLnBZwjboiez/lQKHkwzozRm+KR8Thwq+88= X-Gm-Gg: AY/fxX638QfUhF3XaV+xj3MCXpr9aDjE0Lwb+0tBdX9zLvN0T+Zv0EWp1p7qkifjFiL i77jBk5MXMRYsADoxmuJhpGg7ylIP0sFCRxgiaCpaZfElqsYo0fXUA+QUnQtbG51UbVCE38ec46 hQjYuherydztEbDRHRd0L357rJ1r0wGQCHdhS8z0tFs5GZRYxXyqABej3HKu31u4sAZnTCJXgju 55P11dJEEye+HTtASuXHwUe8342ffggtingmVO4DCt86D3XdnuhWUDCieKqjOUzKI1KD4YRkG0j /SOpulSWEw5UokV8Rf2rUgwYSLcLU9XhkTjAn3sCzYatlDjaKbzXSg/c5DAP2CUdlcbkGPkC826 poH8JGOk9BpekimhFfVq9q0UueODcqsc933iv/BEnJ66d7uwUuhLZ8S3rpQ== X-Received: by 2002:a17:907:94c6:b0:b87:322d:a8d0 with SMTP id a640c23a62f3a-b87677a7effmr444832666b.41.1768479875341; Thu, 15 Jan 2026 04:24:35 -0800 (PST) Received: from localhost ([151.47.157.182]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-b842a4cfe60sm2769696066b.45.2026.01.15.04.24.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 15 Jan 2026 04:24:35 -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 v2 1/3] iio: imu: st_lsm6dsx: Set FIFO ODR for accelerometer and gyroscope only Date: Thu, 15 Jan 2026 13:24:29 +0100 Message-Id: <20260115122431.1014630-2-flavra@baylibre.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20260115122431.1014630-1-flavra@baylibre.com> References: <20260115122431.1014630-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/pANAwAKAe3xO3POlDZfAcsmYgBpaNxlKHlBS2+YWZdjOWGvX/xqPbpahixKnyHdW ADRDgnr6CSJAbMEAAEKAB0WIQSGV4VPlTvcox7DFObt8TtzzpQ2XwUCaWjcZQAKCRDt8TtzzpQ2 XzHzC/9bPAfkua2tvZoY8F95CI+PUh8AHp8chR+la9DAB+xgwuEy1VBfyudpnOd4N2IG/R0cU1u 1dU3twNAuMt9bqfjCS0EYxlpp/PK5gqwmnoKZhpMgWi03YxSeD081GKWlhOoqvocqU2m0HtFxHk AOSEIUPwjRo9Zc38j24m+WSoXatJb9sW5yRP4YO56pS/t8Xy5iU5JnPKYaS+cKcZtEd5QWbFHeT MdtQdq1B0FscrBR5Fqoz4AS26+4H1NlfZXejsZtiInEGW9g7XdwAWYSPsaRtIAg+Gd59EinKpeS pp1n8ebh3+bOR73FMts7lsUoyRaRMzEK5/Y2Psa9Rg7CxbwH+V7vnkFb7N1s9G7uOKOO8m5Ae9H RcnSytiPYvVRyYZyz++f4iZzASIhYML9CSrO8tW/YYAhRgjQ7xJ3TNRjfVcCw03VsOnyyMLYK79 3SEQDdShEEyeX0mIRsNKpAFOqhw9i3o2jb8j0zuMf1sAlZ2gJZF44K7rgDfJoL//+ARMw= 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 Sun Feb 8 05:35:30 2026 Received: from mail-ej1-f54.google.com (mail-ej1-f54.google.com [209.85.218.54]) (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 4F591393DE6 for ; Thu, 15 Jan 2026 12:24:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.54 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768479883; cv=none; b=K0ofxmVcCd2qRFzV4KU6mwzoIiyfFzZdzLV7G8ohpbXIvhWiqvy1557fdx+g/wz9y/7N5nK8GL8ZdL2a5dITNJlI0R4IbOASCNuRqErScAa6KXcZUYYGgKF9JfnPOuWngB46bDB2UXjvrsfBu5R/WlpA6Lp/vrdTitHWTRUZtb8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768479883; c=relaxed/simple; bh=qWSzczDZjcHADdh7F0nneO0NUahbOExMpfsP2Gn6t7A=; h=From:To:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=JRJmoxvVwRyLoY2Y702G9HVW2Bd6yhZRT7TMx0ZOq2JzWBzXfzaToiNjzywr/bQX6xM5JiEmG1elC34vcgIZIJ6aP2bMiS8TkunydPo5baUr2BX8jPhPzqlhO/na2K/PUNxOuT+gqOlhVRHem1EConpwgqWbre3o8kIQCK0VBaE= 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=cPCveE7m; arc=none smtp.client-ip=209.85.218.54 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="cPCveE7m" Received: by mail-ej1-f54.google.com with SMTP id a640c23a62f3a-b79f8f7ea43so207326966b.2 for ; Thu, 15 Jan 2026 04:24:38 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1768479877; x=1769084677; 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=Pl7MdD+eDM82jopyo6YY3oLEVekS1uwuMay0GKT/rzY=; b=cPCveE7mP5iRZbP55LmdzrwBOAp9LP352eITXqdHmn/HN6G8+i8aiaYq5RBWx5I5LO b+3GKwyvPbsE33JgWFjerXJvS742W+d8/++5lhYFNjHFftcVvgk5INyDvbLgjdqMTqBk T6NNBKB4TkbMYErvBj1++JwVKvsX9t7oeexQRI1ksm9+aPzFiQuaKOhjBHkJ9QV4mijU cmU6weiDlpPLqVWxvHWVjM2/SvVbditlnoXVtSuzfgMTnNONKKXD+JJGU5p7YI9we6bg S/jJIo8+3usz2e1qtRn8Vt7nNaFZnW+j+kT9pdSxSSLVbDvG3QLb9akntuRDJWmDHqq2 CeQw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1768479877; x=1769084677; 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=Pl7MdD+eDM82jopyo6YY3oLEVekS1uwuMay0GKT/rzY=; b=WcnhR9q6/it4R+GjbzuEok2Jh7Sf8d0agcM965geh/hyaYyvNhvD2tpNbfkPWMMWDz nMKgCpc6FqPJkV3GUl8R3I059ycZ7vZdYRdBYr7XP2mwWygaSo/hl7RpSlbKk5nmQ2vo pMedadtmuQpLtgwupCRgLvXYBjlDvfUEttBfa4CU83PVLXH8rJRKpo0sXsg3H1lp3xI/ E3f4II74XKD4yC+NzDUnt/CCbeKMj2hg5c67iD0MnZYhd7tQN9nVqZwsimst6Ma1q3P2 lMjLX47grr5fizt6jkxQsW39edI631NULUOWWM1RHdHZ18ewr8RpOCvnmTs+q/b1aZGz kpew== X-Forwarded-Encrypted: i=1; AJvYcCVJHatOWx1eX12x66gZ92DLAe2HhICOvGpXwlczIKy/vMYssPraQOchaKSke8gWTbccWOesLRBNJYIqIEI=@vger.kernel.org X-Gm-Message-State: AOJu0YwF0cSMH1fPzAj3rVAi9xMN2TJ5Sa6gOVg3DW96WMGR/StT+qMF T1zCiL9jqsH0Jnr+lxwTQERcuEiOV8m3ikbUoBk7HA8Su9XUV+/fkvEqIhforZdC014= X-Gm-Gg: AY/fxX6dkw30+wDYdLjooRshtwJHBlMrA8HsixXnzaAVAdbYfHAhCInS44xzdtNf6XJ LZf0cxSlYhRlIRhWpVWcTybq5ebfqqI2uN5iMyfrZe/SAyEe77RAMRiiaLXqYuu9Ztj4vsQuDxW WjV6OxX31v0or/2obgh1RXx6R6RRYCq5yywRvT2RJJJDYzSD5xQXtA4Zc0E4r2rxEiWK8HCPrwB wj/pa0JH/zd9KWp0Kleh91nv9OH/xFkYrIDtbk5/sllhzDyTc4cDn3Z4VZQ+85gmJpg/gSqOugx 3JXlA4iM+u73R7ARW5kQeWwDTYHwHMLI0w/iu2vn8T1ZnPWgKQcq6maiZNYpnANfKipAk5rGB+Z suIVpEWv0t6VbuF2WpC/E7uzDbuiQ3F6YlLX76NDJWrmjm43gVbfagSlbvQ== X-Received: by 2002:a17:907:6e8d:b0:b80:2b9b:39e4 with SMTP id a640c23a62f3a-b87612af6demr531623366b.55.1768479876688; Thu, 15 Jan 2026 04:24:36 -0800 (PST) Received: from localhost ([151.47.157.182]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-b842a4d1c6csm2696436566b.39.2026.01.15.04.24.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 15 Jan 2026 04:24:36 -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 v2 2/3] iio: imu: st_lsm6dsx: Set buffer sampling frequency for accelerometer only Date: Thu, 15 Jan 2026 13:24:30 +0100 Message-Id: <20260115122431.1014630-3-flavra@baylibre.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20260115122431.1014630-1-flavra@baylibre.com> References: <20260115122431.1014630-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=2112; i=flavra@baylibre.com; h=from:subject; bh=qWSzczDZjcHADdh7F0nneO0NUahbOExMpfsP2Gn6t7A=; b=owEB7QES/pANAwAKAe3xO3POlDZfAcsmYgBpaNxlpv437N4QVb6m8Faki+PE65JDHu+70R6ye 0wyqv5/48KJAbMEAAEKAB0WIQSGV4VPlTvcox7DFObt8TtzzpQ2XwUCaWjcZQAKCRDt8TtzzpQ2 XwZhDAChyQPoYHmlfvyiL64ebtVA2ufpzNmsLFkWO2Dvchs/07PTiOq1ayxS4+NMjAaI23xOUpV O/u4rvzkeEeg+XDBtZQpUrPP26zKLYfn2tjDc+VlQLiAXJjhrGnvUhVBanRXfWLb9sFk6NNf5MC QX6wycFcMs1im8al2xqBgey13GmP3zX7Z0suDvFNLgsPXVJuK+MsCU4dvkGNl1heQfoc3pdtxgJ X9HZfDuTh8fuU+ZB0Kyq8wHaFNEAXgJe08DfItwH+pDOAjaijB/pMykncGYSro/YoQUwvgKQzIE RsotOINVzpqeUlxrl604aNNnjwex1kVdQitDOj2BxgAeY0W8VyMGX0/hwvBWBCHAczZcBUy6WpS I0W9leFEHqBKkGfZMLiXmhC39Njy6q8LLFdIGcjYGVocVdjsai0OYlwGcOzyeZwvdltq6RoXbSP S2SwHpNHLBeU1nQ9kvA6Kz6a2K9u4+PqeYD3/zkLDmNZ3oKm+mV2f3+cfH8zHK1cqczjM= 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. To prevent userspace from triggering an out-of-bounds array access, and to support the only use case for which FIFO sampling frequency values different from the sensor sampling frequency may be needed (which is for keeping FIFO data rate low while sampling acceleration data at high rates for accurate event detection), 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..cde29b2e6f34 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 Sun Feb 8 05:35:30 2026 Received: from mail-ej1-f53.google.com (mail-ej1-f53.google.com [209.85.218.53]) (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 B2BF7396B80 for ; Thu, 15 Jan 2026 12:24:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.53 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768479889; cv=none; b=eEDfT7HALVk2BZhFvUeHr1zKMRxaewburVwOoPFF0avJN96rAbTknQvAT5e81hSgs+sOEsnKGJXtjM+DSc3jcV7oagppz3Yvji6SMRjAd2CmRIbq9bxtk3w/NiGXag0jEVO+VCr+oD3HIxU6c3ed1sbgCXtZhchXURRi3Ny+Rkg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768479889; c=relaxed/simple; bh=eAE8bx3nthEXnPAwN1UtDNhmJKqoQvTIIPqqhN93GaU=; h=From:To:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=sh92UXpvhPGN66LbrN03ZJ5n8UgsqpRx4/WSzO7wgYPo65HT0y9SkIgwZTZeqN6XNIMxi54VzURzz03pvsNgdico8k2pLFHCOQ0QSFhySuRNI+DfLMZUm2iSF+ubP3/lA4yz8L1Du1x+GsLfWagrt9H27nGqJZclMbAgGGsB8EM= 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=Sh0mtqrT; arc=none smtp.client-ip=209.85.218.53 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="Sh0mtqrT" Received: by mail-ej1-f53.google.com with SMTP id a640c23a62f3a-b8715a4d9fdso116608766b.0 for ; Thu, 15 Jan 2026 04:24:39 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1768479878; x=1769084678; 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=i6mzEvNPGvJ4fziVk+je0M6PHmlcevtcpm9cWqsEor0=; b=Sh0mtqrTJhrKTpatDGnd0DqssJ5JU7ajfEMmlmwmN0z7Zka+twONIhCPH269YD22R4 Chf7Bb7ZaPErHUi+e+2HgwhL+Yql+qBbQ2/uHly2swYvlfJiK6pBuLU+TKm5+AfOnR2e oeVMs6mlGHYpHXxC+wY3pzEBRjXz4bhhO4LD1wIiq3SZi4MD8oxuB83nbGNJNu8TRu8I d6qnO9JwyuLPiu3aKr4R6Z3ZyNPgguIteWjyT+puQ4wmPWQvRVzJd0OpVWEA/URRdK2B lhcIc3J6kA0vHpi4tIJE0YOmEfWTfxyX8KvrUTT/1waKfM3Z8ivK49kpwJ3rSi+FImJ+ DlsA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1768479878; x=1769084678; 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=i6mzEvNPGvJ4fziVk+je0M6PHmlcevtcpm9cWqsEor0=; b=UdL9l/NKEsGwUOjUlYC860lkK1qr+RNlfNuAZn3GfIxETyagKjDo/uuqXquZKfylVc J0mQX4KscvfZQA1UYLX5AmQszIgbinvxHV7lEWoDe1QgifHsz9ci5vCsQBNZ3kqJthZX gX3raWoI+HH+z0B2jlGFrW/XZu3cOHxFqXp4DdWV9FDstQXlFEVY1vIIj0/F5trIK3gU fpa4tjE/k/HBjh0z//wq0FAJ43/I4sHPbHLlyAs7rOVwyWrp14iUg9fz97nfV6KgCQPG 4xZuasDf5evW8jfxEzEBC2+csO1W0nhC+lzZnuIIV0VbJH6x/DOBrwEB5eef01j6IrlK rC5g== X-Forwarded-Encrypted: i=1; AJvYcCU85ivkVXOKwwtSvW4uzA0Rc+KNRnHjQipbIoVsPLXna0uZR4FsIIr1iEJwJRPBUmuiYLlUzzTTmeYd8V8=@vger.kernel.org X-Gm-Message-State: AOJu0YwVvDw4nbP+gZ1p3YDkhuFOKwgkRUOdm6teKaA8cdD02DcZbRQv PF2RLcsNzAUgNur3ZDl6a5pyOq3DERF65HChXUjdsKzvdhrCCr6EIPOEL435jiH3L0Q= X-Gm-Gg: AY/fxX6Pisw0aXTj4Tv0MZ8gRGPZXqTRCI9KoUl/Q8WiW1XxfqDELLJZh2Zc19fa1/z rfvcdNR/Dwz2SDrH1k1+uBACQ7ZidFH+qk1R0+wwH38k4DyhEv34Kjv4w+SZ7Kq+Q0Qhvp3pc17 /j8Fqf6F294p0iZM4yHVmy1jWuTmnnZup7Zxfl0A3ULW5jEv3vxVpKeGlfCWpm4DSpkA7glSyRL DXIt+BPUBa47TO8tytN9Amg8u3A6772gpuGMN9y7t9FPRwRwdGnAnPGmv4BbTE3ept/njmh6l9A zQsmL0uTjNoeTO3keDJ4fuD/tJTKtAtyMQskKOL1XsHtmAZJcUijk7FdO6EEdTCnSta33ADsOmO WiJFW7Slsg3UQPpuEpWWHoF3R6ZV/w6xfulE9t+xkMw8Oq9K2tCFtOEl78Q== X-Received: by 2002:a17:906:6a09:b0:b87:965:9078 with SMTP id a640c23a62f3a-b8760fcbe64mr436660566b.7.1768479877960; Thu, 15 Jan 2026 04:24:37 -0800 (PST) Received: from localhost ([151.47.157.182]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-b876b6865desm407693166b.12.2026.01.15.04.24.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 15 Jan 2026 04:24:37 -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 v2 3/3] iio: imu: st_lsm6dsx: Add support for rotation sensor Date: Thu, 15 Jan 2026 13:24:31 +0100 Message-Id: <20260115122431.1014630-4-flavra@baylibre.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20260115122431.1014630-1-flavra@baylibre.com> References: <20260115122431.1014630-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=14623; i=flavra@baylibre.com; h=from:subject; bh=eAE8bx3nthEXnPAwN1UtDNhmJKqoQvTIIPqqhN93GaU=; b=owEB7QES/pANAwAKAe3xO3POlDZfAcsmYgBpaNxmqFjb4CwiGPmvIqKChd2gAjf0e1YnApW5+ MgO2Hc8BGGJAbMEAAEKAB0WIQSGV4VPlTvcox7DFObt8TtzzpQ2XwUCaWjcZgAKCRDt8TtzzpQ2 X4ixDAClJyYq9v6llugFdnbebCrjF6xjKL1zs0ypxz+5lb9lUfYYCt1qSpIbZltE0prLKfY1LWl oV5rDfMUgS4zKuJOJs76GpmQHvZK2SCMI0NmAXnlczTCbofODua0zJ5X36jSNaJwh30jLVn02AL ATvvavSEyzMaWhj3/kxQEbjybQbBisqk1nntPIlewI+10beLY28c5kCukc4BmZ29JgdZiPemeXT 3HOlcoHUoHYkubO6Cnr3TU+GSuPPeGBffAefr+PWnT0LJV9GunjTMEnWd6z7bUsYeODy15kyNFv n0VGjs9QuDf5//z2yjiCPyEeqN3YauRpJ5wUPHhz5MQ4AjeeZ3ZUhNHpw5IXOrWvnqCFhmIjWNp yrnAHhZPssfzG09wVzXTQWX72kuCWQrTZX4I+qoLr56JgcOrXz2ODoJ5Hj5TFomqoSbnG5xaAzt zdAr0ILAUGBgF86mxC7YBIY8OzYPMTIQTd0NyTfUE6hKBsN3RXtPovNwSEkEKaxjKp78Y= 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 | 212 ++++++++++++++++++ 5 files changed, 307 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 cde29b2e6f34..1846b9f84c29 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..3594d97a98ff --- /dev/null +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_fusion.c @@ -0,0 +1,212 @@ +// 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= ); + st_lsm6dsx_sf_set_page(hw, false); + + return err; +} + +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); + +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; + u8 odr_val; + + odr_mHz =3D val * MILLI + val2 * MILLI / MICRO; + 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