From nobody Wed Oct 8 02:17:15 2025 Received: from mail-ed1-f50.google.com (mail-ed1-f50.google.com [209.85.208.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 8AF62271473; Wed, 2 Jul 2025 23:03:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.50 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751497419; cv=none; b=Lz7VjOJ8ts8XyYQTIyhLxLOLaOPXIShlo4+yHG8vo9JLou2HrNao278JjLCpWhXxuxh8cPc0bmS7Z7+1ndYeNfMjEKc1dLM4OM2m78vin5CaaNz5X/qsdl1ptAKOfIVCVj96vsoOg+CojUFFR/rsxzZpJYi1erWNMuUxpcEtNnk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751497419; c=relaxed/simple; bh=SRaABmozsgF0f3mE46kXYAgf49NAeAKQ51vLOpdMXlg=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=RcpGbwR8OFM9LHbMB1Vr3rJvffbAReRf8WoYixMT6UWKNgQMef0nWOduq5chgTCDKmXyAlJ6d5ls0gmGH2FpIc8yJErAJK6y/cbEi71hd0YZeIP1LQrwvtgL4ONk7T0CCrEB6PYofjUKtNAlT8Xiz1E9wVIkAPF5+j0EhYzxZyU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=gSavGmzb; arc=none smtp.client-ip=209.85.208.50 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="gSavGmzb" Received: by mail-ed1-f50.google.com with SMTP id 4fb4d7f45d1cf-607780f0793so1519487a12.2; Wed, 02 Jul 2025 16:03:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1751497415; x=1752102215; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=PTqgcGzLOzohiTbEZCmB5DbpLjs82c1oETtUUMblFyM=; b=gSavGmzbJOJ4R3NlC7yg/IXFH6jXcjzvVijnq8X4wdpt/gTEckLIarltF0YttR5B6g ddcC6fVO8jXbPyIk2PC1BCjA+pf1kHiXu++c04pNWKhmbsAEawzXJ1NplgTYCpOup0qi V1djF6NEYpoVZAqBv8b1rLmjdpGEMI6UQ1Qc6uaUZQbrInpskW6zXsOoV4vvEtpKSbFd XyjSyAoQ0bDewW24m3YGNqXnOiR3Ef6c3X6cx3JIwMicvm3aDsgU6yAdbOaNMvK4+jPl W42HJxEE50b2lMICqmCue2CuLuF6L9I86VzlLxY3gxw2dEyjUcGpBDK9T0gPnJ6tE1R/ /gHw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1751497415; x=1752102215; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=PTqgcGzLOzohiTbEZCmB5DbpLjs82c1oETtUUMblFyM=; b=qxXPs8V9IRtLqbtIPHlr0u9l47xxUYoEaxvvaMPCZpXE2ZsZcTA5ff7AXNTNJRaxU5 XkdlKarF7rzHeYhzcegkTH2e1pFhG0BnMiTxz97a5PSYkD2xpNjrZuDfYe861MdQozNN tui6lOQD7lGpssN3gyPdfxOuTHPucWVC1iFStNr/jOYWU2Kk2qrbILqBONXwFVg1/yJ5 AE42AfXnkavhQ7x0cdjuPpeF0snkHP/E7d1TNAA0XfQhGdqlAxp979M4TMVEcxBOw78y SDAGJmSdkn6hGRriyD7ulK2uqEA+zEV9oR31O1/N9d++g1dZ0cgWQOVTLBubilkxfTSl mhWQ== X-Forwarded-Encrypted: i=1; AJvYcCUrQs0o8R+UsGtZNFWdJ1GSe0X5BShezR0U5I1jH0fwK8kEaszSABphMbV8Yrd7kG3L0u9UHeSOAuB8WEcZ@vger.kernel.org, AJvYcCV+cH+o7IrMcFBhkzq0hqTpeeAHfLbc4KEhB5AYponumaL6YbU1ZrL8irnbTlVkeJlgFPYMWVQJHOI=@vger.kernel.org X-Gm-Message-State: AOJu0Yyo+iiVbGhr9uFerUSfUyoobH6de1MTYMuXdeCQ3rxwl3PQ8P0S wAa+6nc1x7lCfnacha2hpnr8zyM10ApAdsNLkAVOwMXZBfT7bf70ihZ7 X-Gm-Gg: ASbGncv17a+nZ4qP9ZDjdYbiJKOIUeZF6apd6y3mEEVuwsiyn08OWJLhVAhvSrY/lfX NNfGVeZJD9wTAnMKfxurmI/KcUpWpU2cvhRohZYSOgW1pqILeOFvt4HHNLYGrmZdUEYlBW8Hs9j NPd7heBbKHk9PiJNacZKfXlHlB4ulqwy4nXzypc3QCyDRABoyUnO3z+o6WwV0+xNNmT2lYDA75d 6QbRv0y10N5QjQV6YYcVLGY2J+n4QZ+wkW9B+V8a5lbZ+yqcsGW2zb0W5fiJXnKyCLL2I0UOjy9 uqIwxZUZYctfiASbRAZOYhYkLfZCdlzxbSxS8rOrbII92awy2unR03VzO2OmZPqRJIp2QalkjkA wggyiBK+rzV2sFg+kJcqQrJIyhfP9vvJz X-Google-Smtp-Source: AGHT+IFhKJNG+ljOldhF4FdYLjOhsK3OLt9cGTnI3B+UArDcStKyqEIKDX5ekKWliVL4hhSqVcvovQ== X-Received: by 2002:a05:6402:2344:b0:606:c63b:e330 with SMTP id 4fb4d7f45d1cf-60e5361114emr1407071a12.11.1751497414664; Wed, 02 Jul 2025 16:03:34 -0700 (PDT) Received: from localhost.localdomain (84-72-156-211.dclient.hispeed.ch. [84.72.156.211]) by smtp.gmail.com with ESMTPSA id 4fb4d7f45d1cf-60c8319e706sm10031469a12.47.2025.07.02.16.03.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 02 Jul 2025 16:03:33 -0700 (PDT) From: Lothar Rubusch To: lars@metafoo.de, Michael.Hennerich@analog.com, jic23@kernel.org, dlechner@baylibre.com, nuno.sa@analog.com, andy@kernel.org, corbet@lwn.net Cc: linux-iio@vger.kernel.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, eraretuya@gmail.com, l.rubusch@gmail.com, Andy Shevchenko Subject: [PATCH v11 1/8] iio: accel: adxl345: simplify interrupt mapping Date: Wed, 2 Jul 2025 23:03:08 +0000 Message-Id: <20250702230315.19297-2-l.rubusch@gmail.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250702230315.19297-1-l.rubusch@gmail.com> References: <20250702230315.19297-1-l.rubusch@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Refactor the sensor interrupt mapping by utilizing regmap_assign_bits(), which accepts a boolean value directly. Introduce a helper function to streamline the identification of the configured interrupt line pin. Also, use identifiers from units.h to represent the full 8-bit register when setting bits. This is a purely refactoring change and does not affect functionality. Signed-off-by: Lothar Rubusch Reviewed-by: Andy Shevchenko --- drivers/iio/accel/adxl345_core.c | 34 +++++++++++++++++++------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/drivers/iio/accel/adxl345_core.c b/drivers/iio/accel/adxl345_c= ore.c index e21ec6c15d15..6c437d7a59ed 100644 --- a/drivers/iio/accel/adxl345_core.c +++ b/drivers/iio/accel/adxl345_core.c @@ -1088,6 +1088,19 @@ static const struct iio_info adxl345_info =3D { .hwfifo_set_watermark =3D adxl345_set_watermark, }; =20 +static int adxl345_get_int_line(struct device *dev, int *irq) +{ + *irq =3D fwnode_irq_get_byname(dev_fwnode(dev), "INT1"); + if (*irq > 0) + return ADXL345_INT1; + + *irq =3D fwnode_irq_get_byname(dev_fwnode(dev), "INT2"); + if (*irq > 0) + return ADXL345_INT2; + + return ADXL345_INT_NONE; +} + /** * adxl345_core_probe() - Probe and setup for the accelerometer. * @dev: Driver model representation of the device @@ -1203,23 +1216,16 @@ int adxl345_core_probe(struct device *dev, struct r= egmap *regmap, if (ret) return ret; =20 - irq =3D fwnode_irq_get_byname(dev_fwnode(dev), "INT1"); - if (irq < 0) { - intio =3D ADXL345_INT2; - irq =3D fwnode_irq_get_byname(dev_fwnode(dev), "INT2"); - if (irq < 0) - intio =3D ADXL345_INT_NONE; - } - + intio =3D adxl345_get_int_line(dev, &irq); if (intio !=3D ADXL345_INT_NONE) { /* - * Any bits set to 0 in the INT map register send their respective - * interrupts to the INT1 pin, whereas bits set to 1 send their respecti= ve - * interrupts to the INT2 pin. The intio shall convert this accordingly. + * In the INT map register, bits set to 0 route their + * corresponding interrupts to the INT1 pin, while bits set to 1 + * route them to the INT2 pin. The intio should handle this + * mapping accordingly. */ - regval =3D intio ? 0xff : 0; - - ret =3D regmap_write(st->regmap, ADXL345_REG_INT_MAP, regval); + ret =3D regmap_assign_bits(st->regmap, ADXL345_REG_INT_MAP, + U8_MAX, intio); if (ret) return ret; =20 --=20 2.39.5 From nobody Wed Oct 8 02:17:15 2025 Received: from mail-ed1-f52.google.com (mail-ed1-f52.google.com [209.85.208.52]) (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 4D36028FAA5; Wed, 2 Jul 2025 23:03:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.52 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751497420; cv=none; b=EUkGWnfbHc6T7ufv4S44THEGIFNbB3n2Jgrg62AjXLsI2YMxn9siXLqmUC7JyC5wBO0I0QHHyMatezin++GsgEkPpJV/mzAvxBMB8Zb6L0NMyzxP+2xeSVMqba4CT6hVnuZi0zAgAkU+iJLJ7Kr9NWADglXw0rkJ60R63DJPwr4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751497420; c=relaxed/simple; bh=FZ8nAIRZea4IRVMadLwfjOygtqx3FeLY5GukWqYb5Gg=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=FGZbJSp2OmAht8uwQsduHjgtXcnIj0VfULPbSZ1j5AsOtM3QjuyYmuGD3x+9bfdX8eViMby7ajp+TTYXJiHfBPllmEZEHBzeMxVYkEx9lKH9xkOCoel5YV4Mytdn1Uygo7SxfF14QMOMxynb1iLkwdWcZ/16DnMKk5d1hGeTabw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=Bvlasr2x; arc=none smtp.client-ip=209.85.208.52 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Bvlasr2x" Received: by mail-ed1-f52.google.com with SMTP id 4fb4d7f45d1cf-608964359f9so1357712a12.1; Wed, 02 Jul 2025 16:03:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1751497417; x=1752102217; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=PyPCkouOx+sPBLrp5JL6rT7I/AtUdrpj+SkokeIMDj0=; b=Bvlasr2xLoT2rtCFMSr+Ys4mcdRm+GrZDT6KwqWrjEPrJPcg5algAUvXtVbxzE66bl 48SelZuYk5mf6nuOAUYEZOp2HaDj7+aHJrP1cILnZOxQlGSq22jXYrjpOCq9viQGat2e 71rj4agpB/WJSb2MfkCVp1eaOVXLvJHCfk4cCyvOEd06HsmBzPXLgEBz1V3yF5OO9IKi SgiiJtkg/E1aF4skQGSkBgjOALMFT2UUbCOUxSedTGGG7rEiwj6FfTfzrm+b0pqkZSnB RkoIPwauvxQvp4Sr1YFgD3NVG4ouz96UA0p6uyzhbIfc9gfS3wMvXvetujjwbCGUtz+d GCnw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1751497417; x=1752102217; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=PyPCkouOx+sPBLrp5JL6rT7I/AtUdrpj+SkokeIMDj0=; b=gXjEbEyvfXreqklW1d1PiofQXBY8Z9BeOw6zykaGD39ALXEOWPDGqA2WFQqie7b+XD g3FSkYlBSZ906giaS60sQDHZhVRKihuVt0SMv38K6F9o5cv7N0R429LRDeTAcrc4M4/g znu2XQkKN8RiFLdncr18gZUsy2C2pNqVvifTKeLo/NiEKEFpOoQlwVNKEO/Qy9NClXlI /hVPb81kZu0B25nWdTgAgpr9L1zrZ/uT2WjnHavZ5uyAwPdRY2vOy3Skf0SBEMX/b3mv D4dDt908clFf6yKZdAkFZUEGw0c/L3lnV71YoPON8Xq165GTVWPgMDoAaW09DOh0DNIC DiPg== X-Forwarded-Encrypted: i=1; AJvYcCUG5HpoJOdotyyHIHumEjbTsk6cP+kqBX0IqchCq8vgmjAiICyMl2RtmEFobNZP2GzEBW3aLMRqj7F+Cnv0@vger.kernel.org, AJvYcCUP8IcUhBKuKtyqp1g5qmkBAKVIv1AGM3bQxVoNik3BbWz+P/IIo7znjm3vRo5ORfECSu3lPL0cB8k=@vger.kernel.org X-Gm-Message-State: AOJu0YztQQ1uylWhXy+cIDup5DbV2ME/uphh/N83LDwmqSJgM/848fCo ZDax5fjKBipNbAd6juCGTFRZSsNYeor6dyfK98/Cywu0iBMqNQsP4DbO X-Gm-Gg: ASbGncvYlCi8+bg/Ifu+3rGI2+rKqFzJnbycdkKv/CHdj6drW3b6ffSHAV7Ri0kGULg x9+EcMa3DQ4fK7GUoZenPQBVY7kaDD6U7yezLVF9DWgm/WcfTU1maoM22h/MFtSgS2enJD+2xVI pE2mQXYaQD2RLdeMNyHfm7pno0Wrn0/VIk+IzYsR6oFuu8PWDYtCx9Ti2JW/oDSFC3vU66Y+lqS goQrFH8bh6Onr+DmVjPDpN9lZI5vdZ6cQAwqxvEMouLWtofwwV1Yw3P5lLCkyGF2HVgle/1Izf1 xKgJCh2e2T0ulJL9L7lpejV54XFTsNJH5ccDg8jzadsyKckPXEW5tvfR6rrvn9TKovb8ghTwgHW YR7vKy/vHev3+ghNWZ0lyJ10pIWXzyi30 X-Google-Smtp-Source: AGHT+IGvn8GG5Kba40wjzQLQHEK7cnhfCnXzNg0OoH7aQYig77GIwzAxYjSou1YJ5+L/wylvXCGITg== X-Received: by 2002:a05:6402:3591:b0:5f8:e24b:c8c1 with SMTP id 4fb4d7f45d1cf-60e7451c9a4mr96466a12.9.1751497417277; Wed, 02 Jul 2025 16:03:37 -0700 (PDT) Received: from localhost.localdomain (84-72-156-211.dclient.hispeed.ch. [84.72.156.211]) by smtp.gmail.com with ESMTPSA id 4fb4d7f45d1cf-60c8319e706sm10031469a12.47.2025.07.02.16.03.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 02 Jul 2025 16:03:36 -0700 (PDT) From: Lothar Rubusch To: lars@metafoo.de, Michael.Hennerich@analog.com, jic23@kernel.org, dlechner@baylibre.com, nuno.sa@analog.com, andy@kernel.org, corbet@lwn.net Cc: linux-iio@vger.kernel.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, eraretuya@gmail.com, l.rubusch@gmail.com Subject: [PATCH v11 2/8] iio: accel: adxl345: simplify reading the FIFO Date: Wed, 2 Jul 2025 23:03:09 +0000 Message-Id: <20250702230315.19297-3-l.rubusch@gmail.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250702230315.19297-1-l.rubusch@gmail.com> References: <20250702230315.19297-1-l.rubusch@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Bulk FIFO reading can be streamlined by eliminating redundant variables and simplifying the process of reading x-, y-, and z-axis measurement sets. This is a refactoring change with no expected impact on functionality. Signed-off-by: Lothar Rubusch --- drivers/iio/accel/adxl345_core.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/iio/accel/adxl345_core.c b/drivers/iio/accel/adxl345_c= ore.c index 6c437d7a59ed..b7dfd0007aa0 100644 --- a/drivers/iio/accel/adxl345_core.c +++ b/drivers/iio/accel/adxl345_core.c @@ -885,15 +885,12 @@ static int adxl345_get_samples(struct adxl345_state *= st) */ static int adxl345_fifo_transfer(struct adxl345_state *st, int samples) { - size_t count; int i, ret =3D 0; =20 - /* count is the 3x the fifo_buf element size, hence 6B */ - count =3D sizeof(st->fifo_buf[0]) * ADXL345_DIRS; for (i =3D 0; i < samples; i++) { - /* read 3x 2 byte elements from base address into next fifo_buf position= */ ret =3D regmap_bulk_read(st->regmap, ADXL345_REG_XYZ_BASE, - st->fifo_buf + (i * count / 2), count); + st->fifo_buf + (i * ADXL345_DIRS), + sizeof(st->fifo_buf[0]) * ADXL345_DIRS); if (ret) return ret; =20 --=20 2.39.5 From nobody Wed Oct 8 02:17:15 2025 Received: from mail-ed1-f45.google.com (mail-ed1-f45.google.com [209.85.208.45]) (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 AB4F02EBDC1; Wed, 2 Jul 2025 23:03:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.45 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751497423; cv=none; b=jflLBrHvj+8Yrv/2yhosW96WlvjPdqzkyeEj1gJRuk4b3Z15xYFUTSw2Fj7Xwsxn8QLF4uysHt51aVx6hFGooG17jvz7ocuWhdrqCSffvdCw98iw2NsRKfpH+crz2sGAv05oKX2/GoH/09kgm3O75APYOXve2QJhbYmKkZKaVps= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751497423; c=relaxed/simple; bh=dXSD3Y9CdFOC7DBI5PmdQ8SOqNP4fSCXkxy9goyX044=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=qHkTkp4hIvPQqI4ltAx97mxCRoho/Zm3HMCRVgTeX6Sh+QuyGtppUYESvoioPHVO8vTjlAAlPPWENzSRultab5cCPcL+KRXBoiSRubcSr9fRXKY0QsgG0yDCflQmBjpUee3ONqcFgT1fXnj7jg2P11/qc8TWHfCVbS2Fu0yZCBI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=S5N8uDs0; arc=none smtp.client-ip=209.85.208.45 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="S5N8uDs0" Received: by mail-ed1-f45.google.com with SMTP id 4fb4d7f45d1cf-6070a8f99ffso1434704a12.3; Wed, 02 Jul 2025 16:03:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1751497420; x=1752102220; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=N/t2LXrBhfR6tCe/TVOle2ATEgtYF3+FI/Wh5WPA3/A=; b=S5N8uDs0XLvpsgYHMLMzAFYCt+5R9rsB5r6RdQBP+9l/F6tOOYHILAKSnUPzKEFMCz 8fjJ+pHMGMkDTquqpKFJPhbjdRUGcywwPyfPoDm3JAwEFVOYCDDL9TiH2b/Uz1+sB+Ti 5mr5tsSgtEz53pgTNaRft9oQeWrMbc1JXEzVc/DPnLthWPuUuSGHYfLi9QPhqVcTffIp Uqd29T+SlfCDIKi22o2yx2xkrC5n3R9XPg3hguL6SB/drB4nujOy9Bu6Tb1xJEAPwKtA Obr1KHYlHr6IXwRT3DAACtrrnC+Qw+oDi4KvajEGR4TWlKHDonAyl4TrXwQrREA1DSJ8 0b9w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1751497420; x=1752102220; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=N/t2LXrBhfR6tCe/TVOle2ATEgtYF3+FI/Wh5WPA3/A=; b=HZDcnl/JtNeZtXf6HtG+3pdVglLQLIu0940JQn1//UYm6VKJT9r/hHleP6s8ItejPp 8sOLsRELZmQLlYcXEkOzk+uxDBvVYR+nsWQhZgtk6ABma2mMAoK5EMqx4oQrDSmV33Tj 8XEgKc04WYQTGeevkTG09q4ORB0Ve5kvma59EjHkBsw8SDWG4ldQu9ubdBLS6cx8ylFt pqM4HYmBFHyF8ehKR56aNSl8G6CpZjpqMAd6be/YYhR4WvCxKXJ5NX7If2ltVs67Ipky pjbbJrMstUTQEmzOrfnqM8Owv5V11ROX0oxKmX88qUJwuQm2avIgFs49cKgHlCOy4tSa 46rw== X-Forwarded-Encrypted: i=1; AJvYcCUuSe+3XqHlmhtX4VnZoat+/75I/Tqx2TzOtgozoJlH8TYe0cVnCWXSryugZ0EPhrnRAVkFD+ovb3k=@vger.kernel.org, AJvYcCWMBauNqlFcU8ZGxLHoNkqldeclS3xwiGozoKE0ovuQ4u0aBa87+zrA9nZOGU4IWpkmPGM7X8kF59A4otPT@vger.kernel.org X-Gm-Message-State: AOJu0YxYwfPnu1uymbLDIBRFmqSgurf2k17lKtPmD4IrgBXZLRRNvOKt TlzwpPtYJ/eNELfC5A4tPSkLOvXTUJizLhjdY3JaKC6U/hk8JxcB8KsJ X-Gm-Gg: ASbGncs8HHe3CDFPFj/iTmiTjKrnvWMuLjA9Gf6htoyFSavE+XXZd8ENz+7gf2lrvxC pDwkyuvXV1mivzl5Q62ti2V2AZCqAIWAMpS8dbFwfxBQv7OCjhAa23qPRbpKZSpptH9iLT5mHEP IWhf+a0W7qrErlCqX9U/g1aa1EAMlblT1oRLkPSknE1uAfLU39VwM9pjeYZlZ4UuiBqriVs0ksN xVVd/tt5MT82+LZ+nTdN4U5DT2tYthmZR0RuRKSRLYn0s+SzngqX3l0KEak0RPpJWlGLbVss66t PxpPtsTo3q8f4CEdS7HUc3LOdbFLky3RuI5WBLq9EszFmQBEzHJVDbEx2DMVXYkYX7Nq30qDDWF TITZIcEx6xC/Ldhai8mr8wfZr+LjLy44P X-Google-Smtp-Source: AGHT+IF5DfIZycpfZgNHK6WlGH0ylLbAbMvmhMH5A+iKdVjNJlzqMfw5bh4OQYyBbzsYJ1As0zA4gQ== X-Received: by 2002:a05:6402:5487:b0:607:7add:8647 with SMTP id 4fb4d7f45d1cf-60e74514bc3mr77375a12.8.1751497419567; Wed, 02 Jul 2025 16:03:39 -0700 (PDT) Received: from localhost.localdomain (84-72-156-211.dclient.hispeed.ch. [84.72.156.211]) by smtp.gmail.com with ESMTPSA id 4fb4d7f45d1cf-60c8319e706sm10031469a12.47.2025.07.02.16.03.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 02 Jul 2025 16:03:38 -0700 (PDT) From: Lothar Rubusch To: lars@metafoo.de, Michael.Hennerich@analog.com, jic23@kernel.org, dlechner@baylibre.com, nuno.sa@analog.com, andy@kernel.org, corbet@lwn.net Cc: linux-iio@vger.kernel.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, eraretuya@gmail.com, l.rubusch@gmail.com Subject: [PATCH v11 3/8] iio: accel: adxl345: add activity event feature Date: Wed, 2 Jul 2025 23:03:10 +0000 Message-Id: <20250702230315.19297-4-l.rubusch@gmail.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250702230315.19297-1-l.rubusch@gmail.com> References: <20250702230315.19297-1-l.rubusch@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Enable the sensor to detect activity and trigger interrupts accordingly. Activity events are determined based on a threshold, which is initialized to a sensible default during probe. This default value is adopted from the legacy ADXL345 input driver to maintain consistent behavior. The combination of activity detection, ODR configuration, and range settings lays the groundwork for the activity/inactivity hysteresis mechanism, which will be implemented in a subsequent patch. As such, portions of this patch prepare switch-case structures to support those upcoming changes. Signed-off-by: Lothar Rubusch --- drivers/iio/accel/adxl345_core.c | 242 ++++++++++++++++++++++++++++++- 1 file changed, 239 insertions(+), 3 deletions(-) diff --git a/drivers/iio/accel/adxl345_core.c b/drivers/iio/accel/adxl345_c= ore.c index b7dfd0007aa0..eb24ee7c4251 100644 --- a/drivers/iio/accel/adxl345_core.c +++ b/drivers/iio/accel/adxl345_core.c @@ -36,11 +36,17 @@ #define ADXL345_REG_TAP_AXIS_MSK GENMASK(2, 0) #define ADXL345_REG_TAP_SUPPRESS_MSK BIT(3) #define ADXL345_REG_TAP_SUPPRESS BIT(3) +#define ADXL345_REG_ACT_AXIS_MSK GENMASK(6, 4) =20 #define ADXL345_TAP_Z_EN BIT(0) #define ADXL345_TAP_Y_EN BIT(1) #define ADXL345_TAP_X_EN BIT(2) =20 +#define ADXL345_ACT_Z_EN BIT(4) +#define ADXL345_ACT_Y_EN BIT(5) +#define ADXL345_ACT_X_EN BIT(6) +#define ADXL345_ACT_XYZ_EN (ADXL345_ACT_Z_EN | ADXL345_ACT_Y_EN | ADXL345= _ACT_X_EN) + /* single/double tap */ enum adxl345_tap_type { ADXL345_SINGLE_TAP, @@ -64,6 +70,19 @@ static const unsigned int adxl345_tap_time_reg[] =3D { [ADXL345_TAP_TIME_DUR] =3D ADXL345_REG_DUR, }; =20 +/* activity/inactivity */ +enum adxl345_activity_type { + ADXL345_ACTIVITY, +}; + +static const unsigned int adxl345_act_int_reg[] =3D { + [ADXL345_ACTIVITY] =3D ADXL345_INT_ACTIVITY, +}; + +static const unsigned int adxl345_act_thresh_reg[] =3D { + [ADXL345_ACTIVITY] =3D ADXL345_REG_THRESH_ACT, +}; + enum adxl345_odr { ADXL345_ODR_0P10HZ =3D 0, ADXL345_ODR_0P20HZ, @@ -144,6 +163,13 @@ struct adxl345_state { }; =20 static const struct iio_event_spec adxl345_events[] =3D { + { + /* activity */ + .type =3D IIO_EV_TYPE_MAG, + .dir =3D IIO_EV_DIR_RISING, + .mask_shared_by_type =3D BIT(IIO_EV_INFO_ENABLE) | + BIT(IIO_EV_INFO_VALUE), + }, { /* single tap */ .type =3D IIO_EV_TYPE_GESTURE, @@ -237,6 +263,87 @@ static int adxl345_set_measure_en(struct adxl345_state= *st, bool en) ADXL345_POWER_CTL_MEASURE, en); } =20 +/* activity / inactivity */ + +static int adxl345_is_act_inact_en(struct adxl345_state *st, + enum adxl345_activity_type type) +{ + unsigned int axis_ctrl; + unsigned int regval; + bool en; + int ret; + + ret =3D regmap_read(st->regmap, ADXL345_REG_ACT_INACT_CTRL, &axis_ctrl); + if (ret) + return ret; + + /* Check if axis for activity are enabled */ + switch (type) { + case ADXL345_ACTIVITY: + en =3D FIELD_GET(ADXL345_ACT_XYZ_EN, axis_ctrl); + if (!en) + return false; + break; + default: + return -EINVAL; + } + + /* Check if specific interrupt is enabled */ + ret =3D regmap_read(st->regmap, ADXL345_REG_INT_ENABLE, ®val); + if (ret) + return ret; + + return adxl345_act_int_reg[type] & regval; +} + +static int adxl345_set_act_inact_en(struct adxl345_state *st, + enum adxl345_activity_type type, + bool cmd_en) +{ + unsigned int axis_ctrl; + unsigned int threshold; + int ret; + + if (cmd_en) { + /* When turning on, check if threshold is valid */ + ret =3D regmap_read(st->regmap, + adxl345_act_thresh_reg[type], + &threshold); + if (ret) + return ret; + + if (!threshold) /* Just ignore the command if threshold is 0 */ + return 0; + } + + /* Start modifying configuration registers */ + ret =3D adxl345_set_measure_en(st, false); + if (ret) + return ret; + + /* Enable axis according to the command */ + switch (type) { + case ADXL345_ACTIVITY: + axis_ctrl =3D ADXL345_ACT_XYZ_EN; + break; + default: + return -EINVAL; + } + + ret =3D regmap_assign_bits(st->regmap, ADXL345_REG_ACT_INACT_CTRL, + axis_ctrl, cmd_en); + if (ret) + return ret; + + /* Enable the interrupt line, according to the command */ + ret =3D regmap_assign_bits(st->regmap, ADXL345_REG_INT_ENABLE, + adxl345_act_int_reg[type], cmd_en); + if (ret) + return ret; + + return adxl345_set_measure_en(st, true); +} + /* tap */ =20 static int _adxl345_set_tap_int(struct adxl345_state *st, @@ -624,6 +731,31 @@ static int adxl345_write_raw(struct iio_dev *indio_dev, return adxl345_set_measure_en(st, true); } =20 +static int adxl345_read_mag_config(struct adxl345_state *st, + enum iio_event_direction dir, + enum adxl345_activity_type type_act) +{ + switch (dir) { + case IIO_EV_DIR_RISING: + return !!adxl345_is_act_inact_en(st, type_act); + default: + return -EINVAL; + } +} + +static int adxl345_write_mag_config(struct adxl345_state *st, + enum iio_event_direction dir, + enum adxl345_activity_type type_act, + bool state) +{ + switch (dir) { + case IIO_EV_DIR_RISING: + return adxl345_set_act_inact_en(st, type_act, state); + default: + return -EINVAL; + } +} + static int adxl345_read_event_config(struct iio_dev *indio_dev, const struct iio_chan_spec *chan, enum iio_event_type type, @@ -634,6 +766,9 @@ static int adxl345_read_event_config(struct iio_dev *in= dio_dev, int ret; =20 switch (type) { + case IIO_EV_TYPE_MAG: + return adxl345_read_mag_config(st, dir, + ADXL345_ACTIVITY); case IIO_EV_TYPE_GESTURE: switch (dir) { case IIO_EV_DIR_SINGLETAP: @@ -665,6 +800,10 @@ static int adxl345_write_event_config(struct iio_dev *= indio_dev, struct adxl345_state *st =3D iio_priv(indio_dev); =20 switch (type) { + case IIO_EV_TYPE_MAG: + return adxl345_write_mag_config(st, dir, + ADXL345_ACTIVITY, + state); case IIO_EV_TYPE_GESTURE: switch (dir) { case IIO_EV_DIR_SINGLETAP: @@ -679,6 +818,58 @@ static int adxl345_write_event_config(struct iio_dev *= indio_dev, } } =20 +static int adxl345_read_mag_value(struct adxl345_state *st, + enum iio_event_direction dir, + enum iio_event_info info, + enum adxl345_activity_type type_act, + int *val, int *val2) +{ + unsigned int threshold; + int ret; + + switch (info) { + case IIO_EV_INFO_VALUE: + switch (dir) { + case IIO_EV_DIR_RISING: + ret =3D regmap_read(st->regmap, + adxl345_act_thresh_reg[type_act], + &threshold); + if (ret) + return ret; + *val =3D 62500 * threshold; + *val2 =3D MICRO; + return IIO_VAL_FRACTIONAL; + default: + return -EINVAL; + } + default: + return -EINVAL; + } +} + +static int adxl345_write_mag_value(struct adxl345_state *st, + enum iio_event_direction dir, + enum iio_event_info info, + enum adxl345_activity_type type_act, + int val, int val2) +{ + switch (info) { + case IIO_EV_INFO_VALUE: + /* Scaling factor 62.5mg/LSB, i.e. ~16g corresponds to 0xff */ + val =3D DIV_ROUND_CLOSEST(val * MICRO + val2, 62500); + switch (dir) { + case IIO_EV_DIR_RISING: + return regmap_write(st->regmap, + adxl345_act_thresh_reg[type_act], + val); + default: + return -EINVAL; + } + default: + return -EINVAL; + } +} + static int adxl345_read_event_value(struct iio_dev *indio_dev, const struct iio_chan_spec *chan, enum iio_event_type type, @@ -691,6 +882,10 @@ static int adxl345_read_event_value(struct iio_dev *in= dio_dev, int ret; =20 switch (type) { + case IIO_EV_TYPE_MAG: + return adxl345_read_mag_value(st, dir, info, + ADXL345_ACTIVITY, + val, val2); case IIO_EV_TYPE_GESTURE: switch (info) { case IIO_EV_INFO_VALUE: @@ -741,6 +936,13 @@ static int adxl345_write_event_value(struct iio_dev *i= ndio_dev, return ret; =20 switch (type) { + case IIO_EV_TYPE_MAG: + ret =3D adxl345_write_mag_value(st, dir, info, + ADXL345_ACTIVITY, + val, val2); + if (ret) + return ret; + break; case IIO_EV_TYPE_GESTURE: switch (info) { case IIO_EV_INFO_VALUE: @@ -980,7 +1182,8 @@ static int adxl345_fifo_push(struct iio_dev *indio_dev, } =20 static int adxl345_push_event(struct iio_dev *indio_dev, int int_stat, - enum iio_modifier tap_dir) + enum iio_modifier tap_dir, + enum iio_modifier act_dir) { s64 ts =3D iio_get_time_ns(indio_dev); struct adxl345_state *st =3D iio_priv(indio_dev); @@ -1007,6 +1210,16 @@ static int adxl345_push_event(struct iio_dev *indio_= dev, int int_stat, return ret; } =20 + if (FIELD_GET(ADXL345_INT_ACTIVITY, int_stat)) { + ret =3D iio_push_event(indio_dev, + IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, act_dir, + IIO_EV_TYPE_MAG, + IIO_EV_DIR_RISING), + ts); + if (ret) + return ret; + } + if (FIELD_GET(ADXL345_INT_WATERMARK, int_stat)) { samples =3D adxl345_get_samples(st); if (samples < 0) @@ -1034,6 +1247,7 @@ static irqreturn_t adxl345_irq_handler(int irq, void = *p) struct adxl345_state *st =3D iio_priv(indio_dev); unsigned int regval; enum iio_modifier tap_dir =3D IIO_NO_MOD; + enum iio_modifier act_dir =3D IIO_NO_MOD; u32 axis_ctrl; int int_stat; int ret; @@ -1042,7 +1256,8 @@ static irqreturn_t adxl345_irq_handler(int irq, void = *p) if (ret) return IRQ_NONE; =20 - if (FIELD_GET(ADXL345_REG_TAP_AXIS_MSK, axis_ctrl)) { + if (FIELD_GET(ADXL345_REG_TAP_AXIS_MSK, axis_ctrl) || + FIELD_GET(ADXL345_REG_ACT_AXIS_MSK, axis_ctrl)) { ret =3D regmap_read(st->regmap, ADXL345_REG_ACT_TAP_STATUS, ®val); if (ret) return IRQ_NONE; @@ -1053,12 +1268,19 @@ static irqreturn_t adxl345_irq_handler(int irq, voi= d *p) tap_dir =3D IIO_MOD_Y; else if (FIELD_GET(ADXL345_TAP_X_EN, regval)) tap_dir =3D IIO_MOD_X; + + if (FIELD_GET(ADXL345_ACT_Z_EN, regval)) + act_dir =3D IIO_MOD_Z; + else if (FIELD_GET(ADXL345_ACT_Y_EN, regval)) + act_dir =3D IIO_MOD_Y; + else if (FIELD_GET(ADXL345_ACT_X_EN, regval)) + act_dir =3D IIO_MOD_X; } =20 if (regmap_read(st->regmap, ADXL345_REG_INT_SOURCE, &int_stat)) return IRQ_NONE; =20 - if (adxl345_push_event(indio_dev, int_stat, tap_dir)) + if (adxl345_push_event(indio_dev, int_stat, tap_dir, act_dir)) goto err; =20 if (FIELD_GET(ADXL345_INT_OVERRUN, int_stat)) @@ -1226,6 +1448,20 @@ int adxl345_core_probe(struct device *dev, struct re= gmap *regmap, if (ret) return ret; =20 + /* + * Initialized with sensible default values to streamline + * sensor operation. These defaults are partly derived from + * the previous input driver for the ADXL345 and partly + * based on the recommendations provided in the datasheet. + */ + ret =3D regmap_write(st->regmap, ADXL345_REG_ACT_INACT_CTRL, 0); + if (ret) + return ret; + + ret =3D regmap_write(st->regmap, ADXL345_REG_THRESH_ACT, 6); + if (ret) + return ret; + ret =3D regmap_write(st->regmap, ADXL345_REG_THRESH_TAP, tap_threshold); if (ret) return ret; --=20 2.39.5 From nobody Wed Oct 8 02:17:15 2025 Received: from mail-ed1-f54.google.com (mail-ed1-f54.google.com [209.85.208.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 6D83E2F5C36; Wed, 2 Jul 2025 23:03:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.54 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751497425; cv=none; b=AkxV/jxc6fMdiVP3zfe9bf8t34YrmE1RzRab/v+54JgT6nxOHm0EXdBWT+PzKzdoOYxYcD3U0ESBrzLJ0yYmPA8H/AEQ4PXlbIx4J6NbpLKck8jfoAWl8whz5c8nzEAY32Z5VKXN4xkuQC2sT9rG/0zQlbtkC8FLcZ1ZDA0bTMg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751497425; c=relaxed/simple; bh=jXYHJC34ZKsq7HW8RbSyr4i2li1lu9fBhD1SSaaGjQc=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version:Content-Type; b=Hw+O7bYtofEeaJUii1UFixr1Gc74MAAaB7dba28LhSnl2zlGMtQaw4VfZn+Ga943jR5yGaBjpBenqFbKHUJ+vbi8ubI9/G0RB1CQukGcMszlt/gXOlEJ64Q+A0k2RBL45v3mWoYs39z9lJXAkvhaF1lAAwu/OBVmC4FsWP9yOUM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=MVXAJsEU; arc=none smtp.client-ip=209.85.208.54 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="MVXAJsEU" Received: by mail-ed1-f54.google.com with SMTP id 4fb4d7f45d1cf-60c733792e9so1456573a12.0; Wed, 02 Jul 2025 16:03:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1751497422; x=1752102222; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=tLjGk5ziASxVYisS3zzqxUx/r+m2wPJrd4YVdsrp2p8=; b=MVXAJsEUSfkAesQdVywni4vfsaqaAyDIH1TdmI0ZvfMCkX/AHL4sMT3QTH7GFNRz1H OnxDnVCEuIR7PnReRyFqZkcKDIyfjcB1PuMkDjj/tdKC2KRMN4NnznjdOFVBTIen/xx1 MFeyp6VoafSRGRbeKGe+FLcMNjKZkLh2VTIueha9iB8Jwsu0i1FnmQnWcCjExa6d3RN0 K39xIVyLs3Y9ho9n8svSO3Boy1QCFzjPCdlNNuKRDlEQmEvgkQ2kfee5nyjR4acrRNvN 92qFg25bwqFGospdSmBepP14OlyOpmitVjctgcW+Jkpg9GboJUg+jG1RFEzqIaDn9iRf sVrg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1751497422; x=1752102222; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=tLjGk5ziASxVYisS3zzqxUx/r+m2wPJrd4YVdsrp2p8=; b=sUl50jPiyon3Qoc8guF54f+oHSLQgE7pPf9j1kXyS6CwPuePekCE+nfOUSLwhEhflD 8wplhqjQ83j2AgcciLiwuhD1eBxnsFOk4XrEavI95deW7rDPT4oxaAYaslaBmV0acCE4 QLa1r1TpBjRGtcSrdZDUUVkfiThDRL27YJxoXdHO5JS+9xvzevC4iTMsJpRT2ShouChE zyImb5JkZh2vGNPrzIUmLoOApWJ8PN9nBj3N/TkIvMKJSnmLpyROsV6ZtKoDdVR9Ti6h jkFYt5xoIbVtmzywPmWDtF+ij40FtvUUUyeGJNBb4Lp+qocoXEMpZm6UJf5k/OfU8osj 3DFQ== X-Forwarded-Encrypted: i=1; AJvYcCUbvwpQFjl5xKvASHp35Prt8pUBVpGQ97JlXFBEAYPOWWY6detJ6bFuuKiE8GFBPHrDpKd3r5rduew=@vger.kernel.org, AJvYcCWANPVjFgxPcWFMrq/8i1IGpjSrLQ6hafUtlEWo7RiC+qf2SyVo13PjZ+RvJCwRmFOMQzr4MF8ZiEtDIy1U@vger.kernel.org X-Gm-Message-State: AOJu0YxT+aqAJULYT7dYGEcMUKvNd/kTXh7CLMR/gVha0W/HAQKahI/3 QDN2a1CZeeowV3SH+4/mocckp04V4dKNPgI61iWXs1roqkZDqR+AQWJT X-Gm-Gg: ASbGnctX7TRuRQTYk25oeKpG+b99F+qC5ijUOxkeVQj7mvxYYh1hj2QzYTVekL5154t sTpGokAXokBOjmSbZe8KnP63H0B21DwqkdLakJLARUEWVlJbX9wInYE1bhEN6wDkR6T5G7eLq6f wEqnz0JL8x0i4hh3a6id8GVRxlWRCUN/oa3qyiyl0bk7xo1OX3LmQcseoJwAjKv8OOt61nStHLF 6V0tIMng3iUPoAH/TqHfluWhgc4fn0YD+OlLToodUUH5egQ9KXFSkjuqN+C5SScZlj4wDPy0yaG KwkDAUsu3I+1n98oabItWl9dH91Hxb6zacaUT0zkeL/3EFySDhFujHC+g8jNamCGgG1gzvSdhHu FQtZc64azwKVuOqh/EVU+EmfSLGCF3y02cyawmjhZMTk= X-Google-Smtp-Source: AGHT+IGm27nFP7+gljUyU+4YSG0cWYTSI1EoK+zgG/JIgPdqMym6pjLQkjKJRFMuZrD/A02skZGdHg== X-Received: by 2002:a05:6402:4490:b0:608:c773:8b3 with SMTP id 4fb4d7f45d1cf-60e768ebf04mr253a12.7.1751497421546; Wed, 02 Jul 2025 16:03:41 -0700 (PDT) Received: from localhost.localdomain (84-72-156-211.dclient.hispeed.ch. [84.72.156.211]) by smtp.gmail.com with ESMTPSA id 4fb4d7f45d1cf-60c8319e706sm10031469a12.47.2025.07.02.16.03.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 02 Jul 2025 16:03:40 -0700 (PDT) From: Lothar Rubusch To: lars@metafoo.de, Michael.Hennerich@analog.com, jic23@kernel.org, dlechner@baylibre.com, nuno.sa@analog.com, andy@kernel.org, corbet@lwn.net Cc: linux-iio@vger.kernel.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, eraretuya@gmail.com, l.rubusch@gmail.com Subject: [PATCH v11 4/8] iio: accel: adxl345: add inactivity feature Date: Wed, 2 Jul 2025 23:03:11 +0000 Message-Id: <20250702230315.19297-5-l.rubusch@gmail.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250702230315.19297-1-l.rubusch@gmail.com> References: <20250702230315.19297-1-l.rubusch@gmail.com> 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 Add support for the sensor=E2=80=99s inactivity feature in the driver. When= both activity and inactivity detection are enabled, the sensor sets a link bit that ties the two functions together. This also enables auto-sleep mode, allowing the sensor to automatically enter sleep state upon detecting inactivity. Inactivity detection relies on a configurable threshold and a specified time period. If sensor measurements remain below the threshold for the defined duration, the sensor transitions to the inactivity state. When an Output Data Rate (ODR) is set, the inactivity time period is automatically adjusted to a sensible default. Higher ODRs result in shorter inactivity timeouts, while lower ODRs allow longer durations-within reasonable upper and lower bounds. This is important because features like auto-sleep operate effectively only between 12.5 Hz and 400 Hz. These defaults are applied when the sample rate is modified, but users can override them by explicitly setting a custom inactivity timeout. Similarly, configuring the g-range provides default threshold values for both activity and inactivity detection. These are implicit defaults meant to simplify configuration, but they can also be manually overridden as needed. Signed-off-by: Lothar Rubusch --- drivers/iio/accel/adxl345_core.c | 238 ++++++++++++++++++++++++++++++- 1 file changed, 234 insertions(+), 4 deletions(-) diff --git a/drivers/iio/accel/adxl345_core.c b/drivers/iio/accel/adxl345_c= ore.c index eb24ee7c4251..90fef42ac021 100644 --- a/drivers/iio/accel/adxl345_core.c +++ b/drivers/iio/accel/adxl345_core.c @@ -37,11 +37,18 @@ #define ADXL345_REG_TAP_SUPPRESS_MSK BIT(3) #define ADXL345_REG_TAP_SUPPRESS BIT(3) #define ADXL345_REG_ACT_AXIS_MSK GENMASK(6, 4) +#define ADXL345_REG_INACT_AXIS_MSK GENMASK(2, 0) +#define ADXL345_POWER_CTL_INACT_MSK (ADXL345_POWER_CTL_AUTO_SLEEP | ADXL34= 5_POWER_CTL_LINK) =20 #define ADXL345_TAP_Z_EN BIT(0) #define ADXL345_TAP_Y_EN BIT(1) #define ADXL345_TAP_X_EN BIT(2) =20 +#define ADXL345_INACT_Z_EN BIT(0) +#define ADXL345_INACT_Y_EN BIT(1) +#define ADXL345_INACT_X_EN BIT(2) +#define ADXL345_INACT_XYZ_EN (ADXL345_INACT_Z_EN | ADXL345_INACT_Y_EN | A= DXL345_INACT_X_EN) + #define ADXL345_ACT_Z_EN BIT(4) #define ADXL345_ACT_Y_EN BIT(5) #define ADXL345_ACT_X_EN BIT(6) @@ -73,14 +80,17 @@ static const unsigned int adxl345_tap_time_reg[] =3D { /* activity/inactivity */ enum adxl345_activity_type { ADXL345_ACTIVITY, + ADXL345_INACTIVITY, }; =20 static const unsigned int adxl345_act_int_reg[] =3D { [ADXL345_ACTIVITY] =3D ADXL345_INT_ACTIVITY, + [ADXL345_INACTIVITY] =3D ADXL345_INT_INACTIVITY, }; =20 static const unsigned int adxl345_act_thresh_reg[] =3D { [ADXL345_ACTIVITY] =3D ADXL345_REG_THRESH_ACT, + [ADXL345_INACTIVITY] =3D ADXL345_REG_THRESH_INACT, }; =20 enum adxl345_odr { @@ -148,6 +158,14 @@ static const int adxl345_fullres_range_tbl[][2] =3D { [ADXL345_16G_RANGE] =3D { 0, 38312 }, }; =20 +/* scaling */ +static const int adxl345_range_factor_tbl[] =3D { + [ADXL345_2G_RANGE] =3D 1, + [ADXL345_4G_RANGE] =3D 2, + [ADXL345_8G_RANGE] =3D 4, + [ADXL345_16G_RANGE] =3D 8, +}; + struct adxl345_state { const struct adxl345_chip_info *info; struct regmap *regmap; @@ -214,10 +232,29 @@ enum adxl345_chans { chan_x, chan_y, chan_z, }; =20 +static const struct iio_event_spec adxl345_fake_chan_events[] =3D { + { + /* inactivity */ + .type =3D IIO_EV_TYPE_MAG, + .dir =3D IIO_EV_DIR_FALLING, + .mask_separate =3D BIT(IIO_EV_INFO_ENABLE), + .mask_shared_by_type =3D BIT(IIO_EV_INFO_VALUE) | + BIT(IIO_EV_INFO_PERIOD), + }, +}; + static const struct iio_chan_spec adxl345_channels[] =3D { ADXL345_CHANNEL(0, chan_x, X), ADXL345_CHANNEL(1, chan_y, Y), ADXL345_CHANNEL(2, chan_z, Z), + { + .type =3D IIO_ACCEL, + .modified =3D 1, + .channel2 =3D IIO_MOD_X_AND_Y_AND_Z, + .scan_index =3D -1, /* Fake channel */ + .event_spec =3D adxl345_fake_chan_events, + .num_event_specs =3D ARRAY_SIZE(adxl345_fake_chan_events), + }, }; =20 static const unsigned long adxl345_scan_masks[] =3D { @@ -265,6 +302,52 @@ static int adxl345_set_measure_en(struct adxl345_state= *st, bool en) =20 /* activity / inactivity */ =20 +/** + * adxl345_set_inact_time - Configure inactivity time explicitly or by ODR. + * @st: The sensor state instance. + * @val_s: A desired time value, between 0 and 255. + * + * Inactivity time can be configured between 1 and 255 seconds. If a user = sets + * val_s to 0, a default inactivity time is calculated automatically (sinc= e 0 is + * also invalid and undefined by the sensor). + * + * In such cases, power consumption should be considered: the inactivity p= eriod + * should be shorter at higher sampling frequencies and longer at lower on= es. + * Specifically, for frequencies above 255 Hz, the default is set to 10 se= conds; + * for frequencies below 10 Hz, it defaults to 255 seconds. + * + * The calculation method subtracts the integer part of the configured sam= ple + * frequency from 255 to estimate the inactivity time in seconds. Sub-Hertz + * values are ignored in this approximation. Since the recommended output = data + * rates (ODRs) for features like activity/inactivity detection, sleep mod= es, + * and free fall range between 12.5 Hz and 400 Hz, frequencies outside this + * range will either use the defined boundary defaults or require explicit + * configuration via val_s. + * + * Return: 0 or error value. + */ +static int adxl345_set_inact_time(struct adxl345_state *st, u32 val_s) +{ + int max_boundary =3D U8_MAX; + int min_boundary =3D 10; + unsigned int val =3D min(val_s, U8_MAX); + enum adxl345_odr odr; + unsigned int regval; + int ret; + + if (val =3D=3D 0) { + ret =3D regmap_read(st->regmap, ADXL345_REG_BW_RATE, ®val); + if (ret) + return ret; + + odr =3D FIELD_GET(ADXL345_BW_RATE_MSK, regval); + val =3D clamp(max_boundary - adxl345_odr_tbl[odr][0], + min_boundary, max_boundary); + } + + return regmap_write(st->regmap, ADXL345_REG_TIME_INACT, val); +} + static int adxl345_is_act_inact_en(struct adxl345_state *st, enum adxl345_activity_type type) { @@ -284,6 +367,11 @@ static int adxl345_is_act_inact_en(struct adxl345_stat= e *st, if (!en) return false; break; + case ADXL345_INACTIVITY: + en =3D FIELD_GET(ADXL345_INACT_XYZ_EN, axis_ctrl); + if (!en) + return false; + break; default: return -EINVAL; } @@ -296,12 +384,32 @@ static int adxl345_is_act_inact_en(struct adxl345_sta= te *st, return adxl345_act_int_reg[type] & regval; } =20 +static int adxl345_set_act_inact_linkbit(struct adxl345_state *st, + enum adxl345_activity_type type, + bool en) +{ + int act_en, inact_en; + + act_en =3D adxl345_is_act_inact_en(st, ADXL345_ACTIVITY); + if (act_en < 0) + return act_en; + + inact_en =3D adxl345_is_act_inact_en(st, ADXL345_INACTIVITY); + if (inact_en < 0) + return inact_en; + + return regmap_assign_bits(st->regmap, ADXL345_REG_POWER_CTL, + ADXL345_POWER_CTL_INACT_MSK, + en && act_en && inact_en); +} + static int adxl345_set_act_inact_en(struct adxl345_state *st, enum adxl345_activity_type type, bool cmd_en) { unsigned int axis_ctrl; unsigned int threshold; + unsigned int period; int ret; =20 if (cmd_en) { @@ -314,6 +422,18 @@ static int adxl345_set_act_inact_en(struct adxl345_sta= te *st, =20 if (!threshold) /* Just ignore the command if threshold is 0 */ return 0; + + /* When turning on inactivity, check if inact time is valid */ + if (type =3D=3D ADXL345_INACTIVITY) { + ret =3D regmap_read(st->regmap, + ADXL345_REG_TIME_INACT, + &period); + if (ret) + return ret; + + if (!period) + return 0; + } } =20 /* Start modifying configuration registers */ @@ -326,6 +446,9 @@ static int adxl345_set_act_inact_en(struct adxl345_stat= e *st, case ADXL345_ACTIVITY: axis_ctrl =3D ADXL345_ACT_XYZ_EN; break; + case ADXL345_INACTIVITY: + axis_ctrl =3D ADXL345_INACT_XYZ_EN; + break; default: return -EINVAL; } @@ -341,6 +464,11 @@ static int adxl345_set_act_inact_en(struct adxl345_sta= te *st, if (ret) return ret; =20 + /* Set link-bit and auto-sleep only when ACT and INACT are enabled */ + ret =3D adxl345_set_act_inact_linkbit(st, type, cmd_en); + if (ret) + return ret; + return adxl345_set_measure_en(st, true); } =20 @@ -573,9 +701,16 @@ static int adxl345_find_odr(struct adxl345_state *st, = int val, =20 static int adxl345_set_odr(struct adxl345_state *st, enum adxl345_odr odr) { - return regmap_update_bits(st->regmap, ADXL345_REG_BW_RATE, + int ret; + + ret =3D regmap_update_bits(st->regmap, ADXL345_REG_BW_RATE, ADXL345_BW_RATE_MSK, FIELD_PREP(ADXL345_BW_RATE_MSK, odr)); + if (ret) + return ret; + + /* update inactivity time by ODR */ + return adxl345_set_inact_time(st, 0); } =20 static int adxl345_find_range(struct adxl345_state *st, int val, int val2, @@ -596,9 +731,49 @@ static int adxl345_find_range(struct adxl345_state *st= , int val, int val2, =20 static int adxl345_set_range(struct adxl345_state *st, enum adxl345_range = range) { - return regmap_update_bits(st->regmap, ADXL345_REG_DATA_FORMAT, + unsigned int act_threshold, inact_threshold; + unsigned int range_old; + unsigned int regval; + int ret; + + ret =3D regmap_read(st->regmap, ADXL345_REG_DATA_FORMAT, ®val); + if (ret) + return ret; + range_old =3D FIELD_GET(ADXL345_DATA_FORMAT_RANGE, regval); + + ret =3D regmap_read(st->regmap, + adxl345_act_thresh_reg[ADXL345_ACTIVITY], + &act_threshold); + if (ret) + return ret; + + ret =3D regmap_read(st->regmap, + adxl345_act_thresh_reg[ADXL345_INACTIVITY], + &inact_threshold); + if (ret) + return ret; + + ret =3D regmap_update_bits(st->regmap, ADXL345_REG_DATA_FORMAT, ADXL345_DATA_FORMAT_RANGE, FIELD_PREP(ADXL345_DATA_FORMAT_RANGE, range)); + if (ret) + return ret; + + act_threshold =3D act_threshold * adxl345_range_factor_tbl[range_old] + / adxl345_range_factor_tbl[range]; + act_threshold =3D min(U8_MAX, max(1, act_threshold)); + + inact_threshold =3D inact_threshold * adxl345_range_factor_tbl[range_old] + / adxl345_range_factor_tbl[range]; + inact_threshold =3D min(U8_MAX, max(1, inact_threshold)); + + ret =3D regmap_write(st->regmap, adxl345_act_thresh_reg[ADXL345_ACTIVITY], + act_threshold); + if (ret) + return ret; + + return regmap_write(st->regmap, adxl345_act_thresh_reg[ADXL345_INACTIVITY= ], + inact_threshold); } =20 static int adxl345_read_avail(struct iio_dev *indio_dev, @@ -733,11 +908,14 @@ static int adxl345_write_raw(struct iio_dev *indio_de= v, =20 static int adxl345_read_mag_config(struct adxl345_state *st, enum iio_event_direction dir, - enum adxl345_activity_type type_act) + enum adxl345_activity_type type_act, + enum adxl345_activity_type type_inact) { switch (dir) { case IIO_EV_DIR_RISING: return !!adxl345_is_act_inact_en(st, type_act); + case IIO_EV_DIR_FALLING: + return !!adxl345_is_act_inact_en(st, type_inact); default: return -EINVAL; } @@ -746,11 +924,14 @@ static int adxl345_read_mag_config(struct adxl345_sta= te *st, static int adxl345_write_mag_config(struct adxl345_state *st, enum iio_event_direction dir, enum adxl345_activity_type type_act, + enum adxl345_activity_type type_inact, bool state) { switch (dir) { case IIO_EV_DIR_RISING: return adxl345_set_act_inact_en(st, type_act, state); + case IIO_EV_DIR_FALLING: + return adxl345_set_act_inact_en(st, type_inact, state); default: return -EINVAL; } @@ -768,7 +949,8 @@ static int adxl345_read_event_config(struct iio_dev *in= dio_dev, switch (type) { case IIO_EV_TYPE_MAG: return adxl345_read_mag_config(st, dir, - ADXL345_ACTIVITY); + ADXL345_ACTIVITY, + ADXL345_INACTIVITY); case IIO_EV_TYPE_GESTURE: switch (dir) { case IIO_EV_DIR_SINGLETAP: @@ -803,6 +985,7 @@ static int adxl345_write_event_config(struct iio_dev *i= ndio_dev, case IIO_EV_TYPE_MAG: return adxl345_write_mag_config(st, dir, ADXL345_ACTIVITY, + ADXL345_INACTIVITY, state); case IIO_EV_TYPE_GESTURE: switch (dir) { @@ -822,9 +1005,11 @@ static int adxl345_read_mag_value(struct adxl345_stat= e *st, enum iio_event_direction dir, enum iio_event_info info, enum adxl345_activity_type type_act, + enum adxl345_activity_type type_inact, int *val, int *val2) { unsigned int threshold; + unsigned int period; int ret; =20 switch (info) { @@ -839,9 +1024,26 @@ static int adxl345_read_mag_value(struct adxl345_stat= e *st, *val =3D 62500 * threshold; *val2 =3D MICRO; return IIO_VAL_FRACTIONAL; + case IIO_EV_DIR_FALLING: + ret =3D regmap_read(st->regmap, + adxl345_act_thresh_reg[type_inact], + &threshold); + if (ret) + return ret; + *val =3D 62500 * threshold; + *val2 =3D MICRO; + return IIO_VAL_FRACTIONAL; default: return -EINVAL; } + case IIO_EV_INFO_PERIOD: + ret =3D regmap_read(st->regmap, + ADXL345_REG_TIME_INACT, + &period); + if (ret) + return ret; + *val =3D period; + return IIO_VAL_INT; default: return -EINVAL; } @@ -851,6 +1053,7 @@ static int adxl345_write_mag_value(struct adxl345_stat= e *st, enum iio_event_direction dir, enum iio_event_info info, enum adxl345_activity_type type_act, + enum adxl345_activity_type type_inact, int val, int val2) { switch (info) { @@ -862,9 +1065,15 @@ static int adxl345_write_mag_value(struct adxl345_sta= te *st, return regmap_write(st->regmap, adxl345_act_thresh_reg[type_act], val); + case IIO_EV_DIR_FALLING: + return regmap_write(st->regmap, + adxl345_act_thresh_reg[type_inact], + val); default: return -EINVAL; } + case IIO_EV_INFO_PERIOD: + return adxl345_set_inact_time(st, val); default: return -EINVAL; } @@ -885,6 +1094,7 @@ static int adxl345_read_event_value(struct iio_dev *in= dio_dev, case IIO_EV_TYPE_MAG: return adxl345_read_mag_value(st, dir, info, ADXL345_ACTIVITY, + ADXL345_INACTIVITY, val, val2); case IIO_EV_TYPE_GESTURE: switch (info) { @@ -939,6 +1149,7 @@ static int adxl345_write_event_value(struct iio_dev *i= ndio_dev, case IIO_EV_TYPE_MAG: ret =3D adxl345_write_mag_value(st, dir, info, ADXL345_ACTIVITY, + ADXL345_INACTIVITY, val, val2); if (ret) return ret; @@ -1220,6 +1431,17 @@ static int adxl345_push_event(struct iio_dev *indio_= dev, int int_stat, return ret; } =20 + if (FIELD_GET(ADXL345_INT_INACTIVITY, int_stat)) { + ret =3D iio_push_event(indio_dev, + IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, + IIO_MOD_X_AND_Y_AND_Z, + IIO_EV_TYPE_MAG, + IIO_EV_DIR_FALLING), + ts); + if (ret) + return ret; + } + if (FIELD_GET(ADXL345_INT_WATERMARK, int_stat)) { samples =3D adxl345_get_samples(st); if (samples < 0) @@ -1458,10 +1680,18 @@ int adxl345_core_probe(struct device *dev, struct r= egmap *regmap, if (ret) return ret; =20 + ret =3D regmap_write(st->regmap, ADXL345_REG_TIME_INACT, 0x37); + if (ret) + return ret; + ret =3D regmap_write(st->regmap, ADXL345_REG_THRESH_ACT, 6); if (ret) return ret; =20 + ret =3D regmap_write(st->regmap, ADXL345_REG_THRESH_INACT, 4); + if (ret) + return ret; + ret =3D regmap_write(st->regmap, ADXL345_REG_THRESH_TAP, tap_threshold); if (ret) return ret; --=20 2.39.5 From nobody Wed Oct 8 02:17:15 2025 Received: from mail-ed1-f49.google.com (mail-ed1-f49.google.com [209.85.208.49]) (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 12DFE2F5C5D; Wed, 2 Jul 2025 23:03:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.49 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751497428; cv=none; b=OgPYTfJUbdoU88zMa9tY3LDn67t6IdXsyhQXNJ9XrqW7KnHgRXYHo1WY3FWwprcBepty0QUITrlbaNxDWyt6T2viAP4Nzg7m5RDXencmBhDKq1pkkxm3RaMKOGzwnyXVsu6gh2v7RZtJ2uNM4Fk2LSsApyIVeF9GW973lTHbLtA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751497428; c=relaxed/simple; bh=6hj0XDYiO26Kjof19ZOBMPRcHJDYPluG+RqJHR5D4pc=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=Q7vrrM1CQRkT3/eUeYrMimcpndA1Bv/XbBZU8874h+++V2xFJ2ztglD6gHoUEKsDyFpNfE22HgmET/g0rcA6zKc3eny3YX97h3cLnTdzsUEIJnl65B7aqqdWrNJvbPLiJewFVdTLgpuYfhYgUU5FL6IONNhTmNljAFb3hyC1P24= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=T27tjw3o; arc=none smtp.client-ip=209.85.208.49 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="T27tjw3o" Received: by mail-ed1-f49.google.com with SMTP id 4fb4d7f45d1cf-608964359f9so1357729a12.1; Wed, 02 Jul 2025 16:03:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1751497424; x=1752102224; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=MQWe/hTusPFEv9JgIS55L59V7GL7W+4vGQLXf/D9JZE=; b=T27tjw3oBsy/62uGIHjfCGu9jwcIUGhF4kRzaOup5kwDLE5JA06pTeYZLf7DoWDyMn g6cHAUXnOzaSu2MsAB9usa1PIYnarkeSHS5OU6/25TVkQmZ99fGzQ4yP/aUhWw1Vo22n /Gd4yL5f+h4gSvfbALykOdqaGZ0nqRcgBfkoTpICEfIaLYK/7B7JUz78pUv19zt4uwcI nUsK4guZl/GujlxVGHx609AEWSinEmRymwN7lgkgc0iZ1z0qIpBOxSNkZsmPm7pl4PBy 3+mBEsS6Zk3bgtE1ogccaiMs8SQLbTeoP3g7sZTRGJyKXbSFb8cvM1mR3UFzqY0SVhcl FdQA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1751497424; x=1752102224; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=MQWe/hTusPFEv9JgIS55L59V7GL7W+4vGQLXf/D9JZE=; b=J5gECE+cSs3pRu/80kCb0/h33vtorExp+TkXlKvB7d9MvMY3J8blqJoKQQ/UZAqaWX jrk3Bs+/EJA2MnIEPhpQAQIByMJOgPGDh8cTg15SR4mTJzNQA9FXuLtIyxigF4gwlyXn yfg8IpTSuw2f8w/mrMpgbuulcIF7TUBOv3be7Uwy4LXFIYZpblSUY1q+pnCZZVl3eify nmNtyg1EszBouCGAuS1IXHuM6WaDknSAPLQdiEP/s01I/5o3zfv4RqpJAZGI5kg+9Tdu cklrPutlszR/xPBcJp1T2Qq/1++50WaF4O2jYksp24Z+HWjLO8IJmm3pff+ZFNhYMzFL SxZQ== X-Forwarded-Encrypted: i=1; AJvYcCWLliguO8S0ScanKJNcIjky22fIK0ayE13NUovKjEpVZTgZOUFogxtxDTB6E1HeFSMBD/zdXM63vw4=@vger.kernel.org, AJvYcCWlpYkB7wMVODxbnAnUPNfL00xijX3wv/iTY1BfSr5r/vLQOeZZa0YlCxr3fR1mVQCKNpQasPL+Wp1Fqx8B@vger.kernel.org X-Gm-Message-State: AOJu0Yw9j2MUX37GM7d6OfpkFveq9P9zaRYWiRGhFXA2sHZn89mYmJEM +iXIvCPIlZsg6CbEwaY5YFnzjf9BQOuVthG9GTK6p2TqWlMnyF4TLNRK X-Gm-Gg: ASbGncvyX02BGue0RryJ0ag9AxF49U9Fxm+nw43i+Uu2uof3/CCSuOehg5MeXkPR+0R IOdTrmY83NTjXKzkhDQbYyDT5yt8PGFJ1qqeSxiq0/4SiLYg1X8syJZkMrjMgE1rtjC34yWfhZG iApF8lagiEES8PMlxeXfVF7YjfNL4nXhxZDzLGaoAawHFMaDtZNHOmcsvNsrkYyMaN3Qy7mWuEx Xb0tZry9HTV/78z3fb2Nqa72DnAGxsL+08QZfUp30PKyn7eDR91LNM5UKlQO+5jQg5pgJfJw3E6 VlhSXjTVn4ohnxEt9om7Y3d8YXJ/B9naSHqn42kQic+d1fkLb92pThKABQlgVGrzipXKW3K3zLq LaRA8PiYb49oCoMKjr/YL3vdXn8Db2pWn X-Google-Smtp-Source: AGHT+IHn+Tw+gjvqGwvhn3JcEZ/mUkCoTMHZ/rpwAOWC4IMaZGhWx4JOJrK9k+GHeHahGtfP4jYkXw== X-Received: by 2002:a05:6402:538f:b0:601:e25d:198a with SMTP id 4fb4d7f45d1cf-60e764f7284mr11367a12.0.1751497424176; Wed, 02 Jul 2025 16:03:44 -0700 (PDT) Received: from localhost.localdomain (84-72-156-211.dclient.hispeed.ch. [84.72.156.211]) by smtp.gmail.com with ESMTPSA id 4fb4d7f45d1cf-60c8319e706sm10031469a12.47.2025.07.02.16.03.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 02 Jul 2025 16:03:43 -0700 (PDT) From: Lothar Rubusch To: lars@metafoo.de, Michael.Hennerich@analog.com, jic23@kernel.org, dlechner@baylibre.com, nuno.sa@analog.com, andy@kernel.org, corbet@lwn.net Cc: linux-iio@vger.kernel.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, eraretuya@gmail.com, l.rubusch@gmail.com Subject: [PATCH v11 5/8] iio: accel: adxl345: add coupling detection for activity/inactivity Date: Wed, 2 Jul 2025 23:03:12 +0000 Message-Id: <20250702230315.19297-6-l.rubusch@gmail.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250702230315.19297-1-l.rubusch@gmail.com> References: <20250702230315.19297-1-l.rubusch@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Enable AC/DC coupling configuration for activity and inactivity detection by setting the AC/DC bit. Extend existing magnitude-based detection with adaptive AC-coupled mode. Use DC-coupled mode to compare acceleration samples directly against configured thresholds. Use AC-coupled mode to compare samples against a reference taken at the start of activity detection. Implement DC-coupled events using MAG, and AC-coupled events using MAG_ADAPTIVE. Expose configuration of thresholds and periods via separate sysfs handles. Note that both coupling modes share the same sensor registers, so activity or inactivity detection cannot be configured for both AC and DC simultaneously. Apply the most recently configured mode. Simplify event handling and support adaptive AC-coupling. Signed-off-by: Lothar Rubusch --- drivers/iio/accel/adxl345_core.c | 252 +++++++++++++++++++++++++++++-- 1 file changed, 238 insertions(+), 14 deletions(-) diff --git a/drivers/iio/accel/adxl345_core.c b/drivers/iio/accel/adxl345_c= ore.c index 90fef42ac021..7038a4effd08 100644 --- a/drivers/iio/accel/adxl345_core.c +++ b/drivers/iio/accel/adxl345_core.c @@ -38,6 +38,8 @@ #define ADXL345_REG_TAP_SUPPRESS BIT(3) #define ADXL345_REG_ACT_AXIS_MSK GENMASK(6, 4) #define ADXL345_REG_INACT_AXIS_MSK GENMASK(2, 0) +#define ADXL345_REG_ACT_ACDC_MSK BIT(7) +#define ADXL345_REG_INACT_ACDC_MSK BIT(3) #define ADXL345_POWER_CTL_INACT_MSK (ADXL345_POWER_CTL_AUTO_SLEEP | ADXL34= 5_POWER_CTL_LINK) =20 #define ADXL345_TAP_Z_EN BIT(0) @@ -54,6 +56,9 @@ #define ADXL345_ACT_X_EN BIT(6) #define ADXL345_ACT_XYZ_EN (ADXL345_ACT_Z_EN | ADXL345_ACT_Y_EN | ADXL345= _ACT_X_EN) =20 +#define ADXL345_COUPLING_DC 0 +#define ADXL345_COUPLING_AC 1 + /* single/double tap */ enum adxl345_tap_type { ADXL345_SINGLE_TAP, @@ -81,16 +86,29 @@ static const unsigned int adxl345_tap_time_reg[] =3D { enum adxl345_activity_type { ADXL345_ACTIVITY, ADXL345_INACTIVITY, + ADXL345_ACTIVITY_AC, + ADXL345_INACTIVITY_AC, }; =20 static const unsigned int adxl345_act_int_reg[] =3D { [ADXL345_ACTIVITY] =3D ADXL345_INT_ACTIVITY, [ADXL345_INACTIVITY] =3D ADXL345_INT_INACTIVITY, + [ADXL345_ACTIVITY_AC] =3D ADXL345_INT_ACTIVITY, + [ADXL345_INACTIVITY_AC] =3D ADXL345_INT_INACTIVITY, }; =20 static const unsigned int adxl345_act_thresh_reg[] =3D { [ADXL345_ACTIVITY] =3D ADXL345_REG_THRESH_ACT, [ADXL345_INACTIVITY] =3D ADXL345_REG_THRESH_INACT, + [ADXL345_ACTIVITY_AC] =3D ADXL345_REG_THRESH_ACT, + [ADXL345_INACTIVITY_AC] =3D ADXL345_REG_THRESH_INACT, +}; + +static const unsigned int adxl345_act_acdc_msk[] =3D { + [ADXL345_ACTIVITY] =3D ADXL345_REG_ACT_ACDC_MSK, + [ADXL345_INACTIVITY] =3D ADXL345_REG_INACT_ACDC_MSK, + [ADXL345_ACTIVITY_AC] =3D ADXL345_REG_ACT_ACDC_MSK, + [ADXL345_INACTIVITY_AC] =3D ADXL345_REG_INACT_ACDC_MSK, }; =20 enum adxl345_odr { @@ -188,6 +206,13 @@ static const struct iio_event_spec adxl345_events[] = =3D { .mask_shared_by_type =3D BIT(IIO_EV_INFO_ENABLE) | BIT(IIO_EV_INFO_VALUE), }, + { + /* activity, ac bit set */ + .type =3D IIO_EV_TYPE_MAG_ADAPTIVE, + .dir =3D IIO_EV_DIR_RISING, + .mask_shared_by_type =3D BIT(IIO_EV_INFO_ENABLE) | + BIT(IIO_EV_INFO_VALUE), + }, { /* single tap */ .type =3D IIO_EV_TYPE_GESTURE, @@ -241,6 +266,14 @@ static const struct iio_event_spec adxl345_fake_chan_e= vents[] =3D { .mask_shared_by_type =3D BIT(IIO_EV_INFO_VALUE) | BIT(IIO_EV_INFO_PERIOD), }, + { + /* inactivity, AC bit set */ + .type =3D IIO_EV_TYPE_MAG_ADAPTIVE, + .dir =3D IIO_EV_DIR_FALLING, + .mask_separate =3D BIT(IIO_EV_INFO_ENABLE), + .mask_shared_by_type =3D BIT(IIO_EV_INFO_VALUE) | + BIT(IIO_EV_INFO_PERIOD), + }, }; =20 static const struct iio_chan_spec adxl345_channels[] =3D { @@ -348,12 +381,114 @@ static int adxl345_set_inact_time(struct adxl345_sta= te *st, u32 val_s) return regmap_write(st->regmap, ADXL345_REG_TIME_INACT, val); } =20 +/** + * adxl345_is_act_inact_ac() - Verify if AC or DC coupling is currently en= abled. + * + * @st: The device data. + * @type: The activity or inactivity type. + * + * Given a type of activity / inactivity combined with either AC coupling = set or + * default to DC, this function verifies if the combination is currently + * configured, hence enabled or not. + * + * Return: true if configured coupling matches the provided type, else a n= egative + * error value. + */ +static int adxl345_is_act_inact_ac(struct adxl345_state *st, + enum adxl345_activity_type type) +{ + unsigned int regval; + bool coupling; + int ret; + + ret =3D regmap_read(st->regmap, ADXL345_REG_ACT_INACT_CTRL, ®val); + if (ret) + return ret; + + coupling =3D adxl345_act_acdc_msk[type] & regval; + + switch (type) { + case ADXL345_ACTIVITY: + case ADXL345_INACTIVITY: + return coupling =3D=3D ADXL345_COUPLING_DC; + case ADXL345_ACTIVITY_AC: + case ADXL345_INACTIVITY_AC: + return coupling =3D=3D ADXL345_COUPLING_AC; + default: + return -EINVAL; + } +} + +/** + * adxl345_set_act_inact_ac() - Configure AC coupling or DC coupling. + * + * @st: The device data. + * @type: Provide a type of activity or inactivity. + * @cmd_en: enable or disable AC coupling. + * + * Enables AC coupling or DC coupling depending on the provided type argum= ent. + * Note: Activity and inactivity can be either AC coupled or DC coupled not + * both at the same time. + * + * Return: 0 if successful, else error value. + */ +static int adxl345_set_act_inact_ac(struct adxl345_state *st, + enum adxl345_activity_type type, + bool cmd_en) +{ + unsigned int act_inact_ac; + + if (type =3D=3D ADXL345_ACTIVITY_AC || type =3D=3D ADXL345_INACTIVITY_AC) + act_inact_ac =3D ADXL345_COUPLING_AC && cmd_en; + else + act_inact_ac =3D ADXL345_COUPLING_DC && cmd_en; + + /* + * A setting of false selects dc-coupled operation, and a setting of + * true enables ac-coupled operation. In dc-coupled operation, the + * current acceleration magnitude is compared directly with + * ADXL345_REG_THRESH_ACT and ADXL345_REG_THRESH_INACT to determine + * whether activity or inactivity is detected. + * + * In ac-coupled operation for activity detection, the acceleration + * value at the start of activity detection is taken as a reference + * value. New samples of acceleration are then compared to this + * reference value, and if the magnitude of the difference exceeds the + * ADXL345_REG_THRESH_ACT value, the device triggers an activity + * interrupt. + * + * Similarly, in ac-coupled operation for inactivity detection, a + * reference value is used for comparison and is updated whenever the + * device exceeds the inactivity threshold. After the reference value + * is selected, the device compares the magnitude of the difference + * between the reference value and the current acceleration with + * ADXL345_REG_THRESH_INACT. If the difference is less than the value in + * ADXL345_REG_THRESH_INACT for the time in ADXL345_REG_TIME_INACT, the + * device is considered inactive and the inactivity interrupt is + * triggered. [quoted from p. 24, ADXL345 datasheet Rev. G] + * + * In a conclusion, the first acceleration snapshot sample which hit the + * threshold in a particular direction is always taken as acceleration + * reference value to that direction. Since for the hardware activity + * and inactivity depend on the x/y/z axis, so do ac and dc coupling. + * Note, this sw driver always enables or disables all three x/y/z axis + * for detection via act_axis_ctrl and inact_axis_ctrl, respectively. + * Where in dc-coupling samples are compared against the thresholds, in + * ac-coupling measurement difference to the first acceleration + * reference value are compared against the threshold. So, ac-coupling + * allows for a bit more dynamic compensation depending on the initial + * sample. + */ + return regmap_assign_bits(st->regmap, ADXL345_REG_ACT_INACT_CTRL, + adxl345_act_acdc_msk[type], act_inact_ac); +} + static int adxl345_is_act_inact_en(struct adxl345_state *st, enum adxl345_activity_type type) { unsigned int axis_ctrl; unsigned int regval; - bool en; + bool int_en, en; int ret; =20 ret =3D regmap_read(st->regmap, ADXL345_REG_ACT_INACT_CTRL, &axis_ctrl); @@ -363,11 +498,13 @@ static int adxl345_is_act_inact_en(struct adxl345_sta= te *st, /* Check if axis for activity are enabled */ switch (type) { case ADXL345_ACTIVITY: + case ADXL345_ACTIVITY_AC: en =3D FIELD_GET(ADXL345_ACT_XYZ_EN, axis_ctrl); if (!en) return false; break; case ADXL345_INACTIVITY: + case ADXL345_INACTIVITY_AC: en =3D FIELD_GET(ADXL345_INACT_XYZ_EN, axis_ctrl); if (!en) return false; @@ -381,23 +518,40 @@ static int adxl345_is_act_inact_en(struct adxl345_sta= te *st, if (ret) return ret; =20 - return adxl345_act_int_reg[type] & regval; + int_en =3D adxl345_act_int_reg[type] & regval; + if (!int_en) + return false; + + /* Check if configured coupling matches provided type */ + return adxl345_is_act_inact_ac(st, type); } =20 static int adxl345_set_act_inact_linkbit(struct adxl345_state *st, enum adxl345_activity_type type, bool en) { + int act_ac_en, inact_ac_en; int act_en, inact_en; =20 act_en =3D adxl345_is_act_inact_en(st, ADXL345_ACTIVITY); if (act_en < 0) return act_en; =20 + act_ac_en =3D adxl345_is_act_inact_en(st, ADXL345_ACTIVITY_AC); + if (act_ac_en < 0) + return act_ac_en; + inact_en =3D adxl345_is_act_inact_en(st, ADXL345_INACTIVITY); if (inact_en < 0) return inact_en; =20 + inact_ac_en =3D adxl345_is_act_inact_en(st, ADXL345_INACTIVITY_AC); + if (inact_ac_en < 0) + return inact_ac_en; + + inact_en =3D inact_en || inact_ac_en; + act_en =3D act_en || act_ac_en; + return regmap_assign_bits(st->regmap, ADXL345_REG_POWER_CTL, ADXL345_POWER_CTL_INACT_MSK, en && act_en && inact_en); @@ -424,7 +578,7 @@ static int adxl345_set_act_inact_en(struct adxl345_stat= e *st, return 0; =20 /* When turning on inactivity, check if inact time is valid */ - if (type =3D=3D ADXL345_INACTIVITY) { + if (type =3D=3D ADXL345_INACTIVITY || type =3D=3D ADXL345_INACTIVITY_AC)= { ret =3D regmap_read(st->regmap, ADXL345_REG_TIME_INACT, &period); @@ -434,6 +588,16 @@ static int adxl345_set_act_inact_en(struct adxl345_sta= te *st, if (!period) return 0; } + } else { + /* + * When turning off an activity, ensure that the correct + * coupling event is specified. This step helps prevent misuse - + * for example, if an AC-coupled activity is active and the + * current call attempts to turn off a DC-coupled activity, this + * inconsistency should be detected here. + */ + if (adxl345_is_act_inact_ac(st, type) <=3D 0) + return 0; } =20 /* Start modifying configuration registers */ @@ -444,9 +608,11 @@ static int adxl345_set_act_inact_en(struct adxl345_sta= te *st, /* Enable axis according to the command */ switch (type) { case ADXL345_ACTIVITY: + case ADXL345_ACTIVITY_AC: axis_ctrl =3D ADXL345_ACT_XYZ_EN; break; case ADXL345_INACTIVITY: + case ADXL345_INACTIVITY_AC: axis_ctrl =3D ADXL345_INACT_XYZ_EN; break; default: @@ -458,6 +624,11 @@ static int adxl345_set_act_inact_en(struct adxl345_sta= te *st, if (ret) return ret; =20 + /* Update AC/DC-coupling according to the command */ + ret =3D adxl345_set_act_inact_ac(st, type, cmd_en); + if (ret) + return ret; + /* Enable the interrupt line, according to the command */ ret =3D regmap_assign_bits(st->regmap, ADXL345_REG_INT_ENABLE, adxl345_act_int_reg[type], cmd_en); @@ -951,6 +1122,10 @@ static int adxl345_read_event_config(struct iio_dev *= indio_dev, return adxl345_read_mag_config(st, dir, ADXL345_ACTIVITY, ADXL345_INACTIVITY); + case IIO_EV_TYPE_MAG_ADAPTIVE: + return adxl345_read_mag_config(st, dir, + ADXL345_ACTIVITY_AC, + ADXL345_INACTIVITY_AC); case IIO_EV_TYPE_GESTURE: switch (dir) { case IIO_EV_DIR_SINGLETAP: @@ -987,6 +1162,11 @@ static int adxl345_write_event_config(struct iio_dev = *indio_dev, ADXL345_ACTIVITY, ADXL345_INACTIVITY, state); + case IIO_EV_TYPE_MAG_ADAPTIVE: + return adxl345_write_mag_config(st, dir, + ADXL345_ACTIVITY_AC, + ADXL345_INACTIVITY_AC, + state); case IIO_EV_TYPE_GESTURE: switch (dir) { case IIO_EV_DIR_SINGLETAP: @@ -1096,6 +1276,11 @@ static int adxl345_read_event_value(struct iio_dev *= indio_dev, ADXL345_ACTIVITY, ADXL345_INACTIVITY, val, val2); + case IIO_EV_TYPE_MAG_ADAPTIVE: + return adxl345_read_mag_value(st, dir, info, + ADXL345_ACTIVITY_AC, + ADXL345_INACTIVITY_AC, + val, val2); case IIO_EV_TYPE_GESTURE: switch (info) { case IIO_EV_INFO_VALUE: @@ -1154,6 +1339,14 @@ static int adxl345_write_event_value(struct iio_dev = *indio_dev, if (ret) return ret; break; + case IIO_EV_TYPE_MAG_ADAPTIVE: + ret =3D adxl345_write_mag_value(st, dir, info, + ADXL345_ACTIVITY_AC, + ADXL345_INACTIVITY_AC, + val, val2); + if (ret) + return ret; + break; case IIO_EV_TYPE_GESTURE: switch (info) { case IIO_EV_INFO_VALUE: @@ -1398,6 +1591,7 @@ static int adxl345_push_event(struct iio_dev *indio_d= ev, int int_stat, { s64 ts =3D iio_get_time_ns(indio_dev); struct adxl345_state *st =3D iio_priv(indio_dev); + unsigned int regval; int samples; int ret =3D -ENOENT; =20 @@ -1422,22 +1616,52 @@ static int adxl345_push_event(struct iio_dev *indio= _dev, int int_stat, } =20 if (FIELD_GET(ADXL345_INT_ACTIVITY, int_stat)) { - ret =3D iio_push_event(indio_dev, - IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, act_dir, - IIO_EV_TYPE_MAG, - IIO_EV_DIR_RISING), - ts); + ret =3D regmap_read(st->regmap, ADXL345_REG_ACT_INACT_CTRL, ®val); + if (ret) + return ret; + + if (FIELD_GET(ADXL345_REG_ACT_ACDC_MSK, regval)) { + /* AC coupled */ + ret =3D iio_push_event(indio_dev, + IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, act_dir, + IIO_EV_TYPE_MAG_ADAPTIVE, + IIO_EV_DIR_RISING), + ts); + + } else { + /* DC coupled, relying on THRESH */ + ret =3D iio_push_event(indio_dev, + IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, act_dir, + IIO_EV_TYPE_MAG, + IIO_EV_DIR_RISING), + ts); + } if (ret) return ret; } =20 if (FIELD_GET(ADXL345_INT_INACTIVITY, int_stat)) { - ret =3D iio_push_event(indio_dev, - IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, - IIO_MOD_X_AND_Y_AND_Z, - IIO_EV_TYPE_MAG, - IIO_EV_DIR_FALLING), - ts); + ret =3D regmap_read(st->regmap, ADXL345_REG_ACT_INACT_CTRL, ®val); + if (ret) + return ret; + + if (FIELD_GET(ADXL345_REG_INACT_ACDC_MSK, regval)) { + /* AC coupled */ + ret =3D iio_push_event(indio_dev, + IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, + IIO_MOD_X_AND_Y_AND_Z, + IIO_EV_TYPE_MAG_ADAPTIVE, + IIO_EV_DIR_FALLING), + ts); + } else { + /* DC coupled, relying on THRESH */ + ret =3D iio_push_event(indio_dev, + IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, + IIO_MOD_X_AND_Y_AND_Z, + IIO_EV_TYPE_MAG, + IIO_EV_DIR_FALLING), + ts); + } if (ret) return ret; } --=20 2.39.5 From nobody Wed Oct 8 02:17:15 2025 Received: from mail-ed1-f50.google.com (mail-ed1-f50.google.com [209.85.208.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 416D52F6F98; Wed, 2 Jul 2025 23:03:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.50 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751497430; cv=none; b=qQ4kxUWFgx7SGgzb0nwL+qtGwygj7oWUlj1ffSNuhcGXAtTTexueuNedxeZ9clM+pNbiAn0AqROcXi2RpPhr90y3S6pdlJ2mDr9AUe1u+f/J/kEPqbb2MvoiEglAXyBSE2KqUHxClINN8h7FnMj+pCb3wtkhWA4ucvNIJadK6Ck= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751497430; c=relaxed/simple; bh=s+C0yL1hXzubu2/nbnuUG6U6nRsLcXLdwHincapmv8g=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=hpi9uBI6FyN2Q7pvtt1SglaTX1AqBr7rn66JCYGlayIDTYXQvrQdRztRBVU2t/3ichIdYV8b33zBkEBfPksIu8aovXA0FNsqDYtSv6JDBsKZ4F5wvmqTNngkq8mr7GNCzFrGDKZwTeU2eYlA9iRVbqJokCG+HJe3NYGQsCj3Aug= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=nQVGKjuj; arc=none smtp.client-ip=209.85.208.50 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="nQVGKjuj" Received: by mail-ed1-f50.google.com with SMTP id 4fb4d7f45d1cf-606a269d440so1563375a12.2; Wed, 02 Jul 2025 16:03:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1751497427; x=1752102227; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=DZDY8jLX7yIHyfhWXatG/QVlYNUsLcUkgMuRqMMKogY=; b=nQVGKjuj8OjPHDjGPLEUbPJYWFX9Joq5RCMbDKNhoUGVbk9jL2NaAcKwf81o6mnugo Zz/Iq/YCjwQtfPhROLbWrLvF0ZOLfjhs3k1pVJnc42Yy6SSPu6xgLk5W6gQLQ0gcqWoj BxTjLD1ey7tDP0f5qkPSVjr+rU/3PoSG0RoE/HEfyjRQ8Khc9QU63GlbMEJYujUcOsJW qCXe47uPUzxEx9f5egey7z5odB+q9bdc2/TDEH2uw78a7zY+J2DGoUU3r8N5tbudFn5K H2Qn5+XIdLjX9r0l3DZTfP+vJ9y/DEb3It6kN8ZZajj6E4/wzq9miSvwTdBAdJwLhuYQ g1xA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1751497427; x=1752102227; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=DZDY8jLX7yIHyfhWXatG/QVlYNUsLcUkgMuRqMMKogY=; b=xCJ0Pgq6v4/yyPiKJxTYI0ysjkJ79JugD8xRqD9UD5P2qneKXzK3fy6yDItbSTyk6O XX2ycOdZ8lkRaJDn2VvEgM8u13DLGvmTiPNRbwLkLyvDp34v4mqi8W6VB3HZKS5Qzepq I2nJnd9mYe0oAfmNQTqdXqmhXlQ6Jo6zLSfghKvfegQqK+laH7p9lW1rdKtrCCNSUpTa oAMk5FSdF8bfGtc2ZavZUBDPucIKmUzPD8ys9QoQpHGeWg4otF0El/2q1fxQma3e0ZVu JmQdGvkGwnnarjygzxnWCLPhTssTDVHd6LWSgv5b+K6lyZIjQ6XecKnyktGiNzyi28rs 1cbA== X-Forwarded-Encrypted: i=1; AJvYcCUJ7fNZrLKzPSZaGRpm9Bo2LZ3BG3A3EiNR/c/1Aaqb87F2U2HVSg/EhADkJ9mXF6pGr8j6fQuCp/g=@vger.kernel.org, AJvYcCXeubnhJUIWq/5uF6Lschzz4dXsnX3XEIqAQajIGpKuq6SRLT4c3Ogx6OclEJWEs3uLmnZc7Vgvt4FH3xpo@vger.kernel.org X-Gm-Message-State: AOJu0YzFppJWZWRIwKi3QEa2WzikWCiRzEfBf8woQMpmi73QyTwZ1035 gUOROVs0bkPxb28Sz+XYBOTg93BA5EE79Cc2OdnShYj772Zv1evCrcbUep5+jA== X-Gm-Gg: ASbGncs7pCBLeeMe7Wz/1v86WyZ5qgqelpYpzpr527G2dFhW34djLUJ31vVVMMDuIJX gHUuP81nEOSnSuHjwzAoYUrp4OeSYjk1V9yRrlzVM2/LxFb8UngxtPdJBrJwZ3dyWyf7SL2YfK0 ofCCCreZsvVxzDAkaWk86EtgnisDHOO8D08XRjP+po93GrOFv0uUnav0PHTrDABDSKMaAZUISmD MaUtOwN3jfsPIp4vMQTutG27+MsqiJmug+VVDucOdZBO1MUXm9+ao64brqw550DFMb8jlvqb4yO leOfNcBtSM0y1JnNKWVtBhVEGPq7giRnWweN/ngjbncwoF10r7sYnFI49CjWAX3cc8oIGUOZx6h p4DQdogAyGQUdlFPTs5x+p8j1ls6prlO/ X-Google-Smtp-Source: AGHT+IHIN88VU1mwRV0L8bi40hMCRkMIx/OwlCCCnwoljUwi2PoJ3thzEpuuVI9+SjCK0tqbS/MhBA== X-Received: by 2002:a05:6402:4311:b0:606:e469:2532 with SMTP id 4fb4d7f45d1cf-60e7454922dmr106961a12.10.1751497426434; Wed, 02 Jul 2025 16:03:46 -0700 (PDT) Received: from localhost.localdomain (84-72-156-211.dclient.hispeed.ch. [84.72.156.211]) by smtp.gmail.com with ESMTPSA id 4fb4d7f45d1cf-60c8319e706sm10031469a12.47.2025.07.02.16.03.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 02 Jul 2025 16:03:45 -0700 (PDT) From: Lothar Rubusch To: lars@metafoo.de, Michael.Hennerich@analog.com, jic23@kernel.org, dlechner@baylibre.com, nuno.sa@analog.com, andy@kernel.org, corbet@lwn.net Cc: linux-iio@vger.kernel.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, eraretuya@gmail.com, l.rubusch@gmail.com Subject: [PATCH v11 6/8] iio: accel: adxl345: extend inactivity time for less than 1s Date: Wed, 2 Jul 2025 23:03:13 +0000 Message-Id: <20250702230315.19297-7-l.rubusch@gmail.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250702230315.19297-1-l.rubusch@gmail.com> References: <20250702230315.19297-1-l.rubusch@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Inactivity and free-fall events are essentially the same type of sensor events. Therefore, inactivity detection (normally set for periods between 1 and 255 seconds) can be extended for shorter durations to support free-fall detection. For periods shorter than 1 second, the driver automatically configures the threshold and duration using the free-fall register. For periods longer than 1 second, it uses the inactivity threshold and duration using the inactivity registers. When using the free-fall register, the link bit is not set, which means auto-sleep cannot be enabled if activity detection is also active. Signed-off-by: Lothar Rubusch --- drivers/iio/accel/adxl345_core.c | 201 +++++++++++++++++++++---------- 1 file changed, 139 insertions(+), 62 deletions(-) diff --git a/drivers/iio/accel/adxl345_core.c b/drivers/iio/accel/adxl345_c= ore.c index 7038a4effd08..614d29e3ed2e 100644 --- a/drivers/iio/accel/adxl345_core.c +++ b/drivers/iio/accel/adxl345_core.c @@ -40,12 +40,15 @@ #define ADXL345_REG_INACT_AXIS_MSK GENMASK(2, 0) #define ADXL345_REG_ACT_ACDC_MSK BIT(7) #define ADXL345_REG_INACT_ACDC_MSK BIT(3) +#define ADXL345_REG_NO_ACDC_MSK 0x00 #define ADXL345_POWER_CTL_INACT_MSK (ADXL345_POWER_CTL_AUTO_SLEEP | ADXL34= 5_POWER_CTL_LINK) =20 #define ADXL345_TAP_Z_EN BIT(0) #define ADXL345_TAP_Y_EN BIT(1) #define ADXL345_TAP_X_EN BIT(2) =20 +#define ADXL345_ACT_INACT_NO_AXIS_EN 0x00 + #define ADXL345_INACT_Z_EN BIT(0) #define ADXL345_INACT_Y_EN BIT(1) #define ADXL345_INACT_X_EN BIT(2) @@ -88,6 +91,7 @@ enum adxl345_activity_type { ADXL345_INACTIVITY, ADXL345_ACTIVITY_AC, ADXL345_INACTIVITY_AC, + ADXL345_INACTIVITY_FF, }; =20 static const unsigned int adxl345_act_int_reg[] =3D { @@ -95,6 +99,7 @@ static const unsigned int adxl345_act_int_reg[] =3D { [ADXL345_INACTIVITY] =3D ADXL345_INT_INACTIVITY, [ADXL345_ACTIVITY_AC] =3D ADXL345_INT_ACTIVITY, [ADXL345_INACTIVITY_AC] =3D ADXL345_INT_INACTIVITY, + [ADXL345_INACTIVITY_FF] =3D ADXL345_INT_FREE_FALL, }; =20 static const unsigned int adxl345_act_thresh_reg[] =3D { @@ -102,6 +107,7 @@ static const unsigned int adxl345_act_thresh_reg[] =3D { [ADXL345_INACTIVITY] =3D ADXL345_REG_THRESH_INACT, [ADXL345_ACTIVITY_AC] =3D ADXL345_REG_THRESH_ACT, [ADXL345_INACTIVITY_AC] =3D ADXL345_REG_THRESH_INACT, + [ADXL345_INACTIVITY_FF] =3D ADXL345_REG_THRESH_FF, }; =20 static const unsigned int adxl345_act_acdc_msk[] =3D { @@ -109,6 +115,7 @@ static const unsigned int adxl345_act_acdc_msk[] =3D { [ADXL345_INACTIVITY] =3D ADXL345_REG_INACT_ACDC_MSK, [ADXL345_ACTIVITY_AC] =3D ADXL345_REG_ACT_ACDC_MSK, [ADXL345_INACTIVITY_AC] =3D ADXL345_REG_INACT_ACDC_MSK, + [ADXL345_INACTIVITY_FF] =3D ADXL345_REG_NO_ACDC_MSK, }; =20 enum adxl345_odr { @@ -191,6 +198,9 @@ struct adxl345_state { u8 watermark; u8 fifo_mode; =20 + u8 inact_threshold; + u32 inact_time_ms; + u32 tap_duration_us; u32 tap_latent_us; u32 tap_window_us; @@ -335,10 +345,72 @@ static int adxl345_set_measure_en(struct adxl345_stat= e *st, bool en) =20 /* activity / inactivity */ =20 +static int adxl345_set_inact_threshold(struct adxl345_state *st, + unsigned int threshold) +{ + int ret; + + st->inact_threshold =3D min(U8_MAX, threshold); + + ret =3D regmap_write(st->regmap, + adxl345_act_thresh_reg[ADXL345_INACTIVITY], + st->inact_threshold); + if (ret) + return ret; + + return regmap_write(st->regmap, + adxl345_act_thresh_reg[ADXL345_INACTIVITY_FF], + st->inact_threshold); +} + +static int adxl345_set_default_time(struct adxl345_state *st) +{ + int max_boundary =3D U8_MAX; + int min_boundary =3D 10; + enum adxl345_odr odr; + unsigned int regval; + unsigned int val; + int ret; + + /* Generated inactivity time based on ODR */ + ret =3D regmap_read(st->regmap, ADXL345_REG_BW_RATE, ®val); + if (ret) + return ret; + + odr =3D FIELD_GET(ADXL345_BW_RATE_MSK, regval); + val =3D clamp(max_boundary - adxl345_odr_tbl[odr][0], + min_boundary, max_boundary); + st->inact_time_ms =3D MILLI * val; + + /* Inactivity time in s */ + return regmap_write(st->regmap, ADXL345_REG_TIME_INACT, val); +} + +static int adxl345_set_inactivity_time(struct adxl345_state *st, u32 val_i= nt) +{ + st->inact_time_ms =3D MILLI * val_int; + + return regmap_write(st->regmap, ADXL345_REG_TIME_INACT, val_int); +} + +static int adxl345_set_freefall_time(struct adxl345_state *st, u32 val_fra= ct) +{ + /* + * Datasheet max. value is 255 * 5000 us =3D 1.275000 seconds. + * + * Recommended values between 100ms and 350ms (0x14 to 0x46) + */ + st->inact_time_ms =3D DIV_ROUND_UP(val_fract, MILLI); + + return regmap_write(st->regmap, ADXL345_REG_TIME_FF, + DIV_ROUND_CLOSEST(val_fract, 5)); +} + /** * adxl345_set_inact_time - Configure inactivity time explicitly or by ODR. * @st: The sensor state instance. - * @val_s: A desired time value, between 0 and 255. + * @val_int: The inactivity time, integer part. + * @val_fract: The inactivity time, fractional part when val_int is 0. * * Inactivity time can be configured between 1 and 255 seconds. If a user = sets * val_s to 0, a default inactivity time is calculated automatically (sinc= e 0 is @@ -359,26 +431,24 @@ static int adxl345_set_measure_en(struct adxl345_stat= e *st, bool en) * * Return: 0 or error value. */ -static int adxl345_set_inact_time(struct adxl345_state *st, u32 val_s) +static int adxl345_set_inact_time(struct adxl345_state *st, u32 val_int, + u32 val_fract) { - int max_boundary =3D U8_MAX; - int min_boundary =3D 10; - unsigned int val =3D min(val_s, U8_MAX); - enum adxl345_odr odr; - unsigned int regval; - int ret; - - if (val =3D=3D 0) { - ret =3D regmap_read(st->regmap, ADXL345_REG_BW_RATE, ®val); - if (ret) - return ret; - - odr =3D FIELD_GET(ADXL345_BW_RATE_MSK, regval); - val =3D clamp(max_boundary - adxl345_odr_tbl[odr][0], - min_boundary, max_boundary); + if (val_int > 0) { + /* Time >=3D 1s, inactivity */ + return adxl345_set_inactivity_time(st, val_int); + } else if (val_int =3D=3D 0) { + if (val_fract > 0) { + /* Time < 1s, free-fall */ + return adxl345_set_freefall_time(st, val_fract); + } else if (val_fract =3D=3D 0) { + /* Time =3D=3D 0.0s */ + return adxl345_set_default_time(st); + } } =20 - return regmap_write(st->regmap, ADXL345_REG_TIME_INACT, val); + /* Do not support negative or wrong input. */ + return -EINVAL; } =20 /** @@ -401,6 +471,9 @@ static int adxl345_is_act_inact_ac(struct adxl345_state= *st, bool coupling; int ret; =20 + if (type =3D=3D ADXL345_INACTIVITY_FF) + return true; + ret =3D regmap_read(st->regmap, ADXL345_REG_ACT_INACT_CTRL, ®val); if (ret) return ret; @@ -509,6 +582,9 @@ static int adxl345_is_act_inact_en(struct adxl345_state= *st, if (!en) return false; break; + case ADXL345_INACTIVITY_FF: + en =3D true; + break; default: return -EINVAL; } @@ -541,15 +617,20 @@ static int adxl345_set_act_inact_linkbit(struct adxl3= 45_state *st, if (act_ac_en < 0) return act_ac_en; =20 - inact_en =3D adxl345_is_act_inact_en(st, ADXL345_INACTIVITY); - if (inact_en < 0) - return inact_en; + if (type =3D=3D ADXL345_INACTIVITY_FF) { + inact_en =3D false; + } else { + inact_en =3D adxl345_is_act_inact_en(st, ADXL345_INACTIVITY); + if (inact_en < 0) + return inact_en; + + inact_ac_en =3D adxl345_is_act_inact_en(st, ADXL345_INACTIVITY_AC); + if (inact_ac_en < 0) + return inact_ac_en; =20 - inact_ac_en =3D adxl345_is_act_inact_en(st, ADXL345_INACTIVITY_AC); - if (inact_ac_en < 0) - return inact_ac_en; + inact_en =3D inact_en || inact_ac_en; + } =20 - inact_en =3D inact_en || inact_ac_en; act_en =3D act_en || act_ac_en; =20 return regmap_assign_bits(st->regmap, ADXL345_REG_POWER_CTL, @@ -568,11 +649,15 @@ static int adxl345_set_act_inact_en(struct adxl345_st= ate *st, =20 if (cmd_en) { /* When turning on, check if threshold is valid */ - ret =3D regmap_read(st->regmap, - adxl345_act_thresh_reg[type], - &threshold); - if (ret) - return ret; + if (type =3D=3D ADXL345_ACTIVITY || type =3D=3D ADXL345_ACTIVITY_AC) { + ret =3D regmap_read(st->regmap, + adxl345_act_thresh_reg[type], + &threshold); + if (ret) + return ret; + } else { + threshold =3D st->inact_threshold; + } =20 if (!threshold) /* Just ignore the command if threshold is 0 */ return 0; @@ -615,6 +700,9 @@ static int adxl345_set_act_inact_en(struct adxl345_stat= e *st, case ADXL345_INACTIVITY_AC: axis_ctrl =3D ADXL345_INACT_XYZ_EN; break; + case ADXL345_INACTIVITY_FF: + axis_ctrl =3D ADXL345_ACT_INACT_NO_AXIS_EN; + break; default: return -EINVAL; } @@ -881,7 +969,7 @@ static int adxl345_set_odr(struct adxl345_state *st, en= um adxl345_odr odr) return ret; =20 /* update inactivity time by ODR */ - return adxl345_set_inact_time(st, 0); + return adxl345_set_inact_time(st, 0, 0); } =20 static int adxl345_find_range(struct adxl345_state *st, int val, int val2, @@ -918,12 +1006,6 @@ static int adxl345_set_range(struct adxl345_state *st= , enum adxl345_range range) if (ret) return ret; =20 - ret =3D regmap_read(st->regmap, - adxl345_act_thresh_reg[ADXL345_INACTIVITY], - &inact_threshold); - if (ret) - return ret; - ret =3D regmap_update_bits(st->regmap, ADXL345_REG_DATA_FORMAT, ADXL345_DATA_FORMAT_RANGE, FIELD_PREP(ADXL345_DATA_FORMAT_RANGE, range)); @@ -934,6 +1016,7 @@ static int adxl345_set_range(struct adxl345_state *st,= enum adxl345_range range) / adxl345_range_factor_tbl[range]; act_threshold =3D min(U8_MAX, max(1, act_threshold)); =20 + inact_threshold =3D st->inact_threshold; inact_threshold =3D inact_threshold * adxl345_range_factor_tbl[range_old] / adxl345_range_factor_tbl[range]; inact_threshold =3D min(U8_MAX, max(1, inact_threshold)); @@ -943,8 +1026,7 @@ static int adxl345_set_range(struct adxl345_state *st,= enum adxl345_range range) if (ret) return ret; =20 - return regmap_write(st->regmap, adxl345_act_thresh_reg[ADXL345_INACTIVITY= ], - inact_threshold); + return adxl345_set_inact_threshold(st, inact_threshold); } =20 static int adxl345_read_avail(struct iio_dev *indio_dev, @@ -1189,7 +1271,6 @@ static int adxl345_read_mag_value(struct adxl345_stat= e *st, int *val, int *val2) { unsigned int threshold; - unsigned int period; int ret; =20 switch (info) { @@ -1205,25 +1286,16 @@ static int adxl345_read_mag_value(struct adxl345_st= ate *st, *val2 =3D MICRO; return IIO_VAL_FRACTIONAL; case IIO_EV_DIR_FALLING: - ret =3D regmap_read(st->regmap, - adxl345_act_thresh_reg[type_inact], - &threshold); - if (ret) - return ret; - *val =3D 62500 * threshold; + *val =3D 62500 * st->inact_threshold; *val2 =3D MICRO; return IIO_VAL_FRACTIONAL; default: return -EINVAL; } case IIO_EV_INFO_PERIOD: - ret =3D regmap_read(st->regmap, - ADXL345_REG_TIME_INACT, - &period); - if (ret) - return ret; - *val =3D period; - return IIO_VAL_INT; + *val =3D st->inact_time_ms; + *val2 =3D MILLI; + return IIO_VAL_FRACTIONAL; default: return -EINVAL; } @@ -1246,14 +1318,12 @@ static int adxl345_write_mag_value(struct adxl345_s= tate *st, adxl345_act_thresh_reg[type_act], val); case IIO_EV_DIR_FALLING: - return regmap_write(st->regmap, - adxl345_act_thresh_reg[type_inact], - val); + return adxl345_set_inact_threshold(st, val); default: return -EINVAL; } case IIO_EV_INFO_PERIOD: - return adxl345_set_inact_time(st, val); + return adxl345_set_inact_time(st, val, val2); default: return -EINVAL; } @@ -1666,6 +1736,17 @@ static int adxl345_push_event(struct iio_dev *indio_= dev, int int_stat, return ret; } =20 + if (FIELD_GET(ADXL345_INT_FREE_FALL, int_stat)) { + ret =3D iio_push_event(indio_dev, + IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, + IIO_MOD_X_AND_Y_AND_Z, + IIO_EV_TYPE_MAG, + IIO_EV_DIR_FALLING), + ts); + if (ret) + return ret; + } + if (FIELD_GET(ADXL345_INT_WATERMARK, int_stat)) { samples =3D adxl345_get_samples(st); if (samples < 0) @@ -1904,15 +1985,11 @@ int adxl345_core_probe(struct device *dev, struct r= egmap *regmap, if (ret) return ret; =20 - ret =3D regmap_write(st->regmap, ADXL345_REG_TIME_INACT, 0x37); - if (ret) - return ret; - ret =3D regmap_write(st->regmap, ADXL345_REG_THRESH_ACT, 6); if (ret) return ret; =20 - ret =3D regmap_write(st->regmap, ADXL345_REG_THRESH_INACT, 4); + ret =3D adxl345_set_inact_threshold(st, 4); if (ret) return ret; =20 --=20 2.39.5 From nobody Wed Oct 8 02:17:15 2025 Received: from mail-ed1-f44.google.com (mail-ed1-f44.google.com [209.85.208.44]) (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 E47692F7CE9; Wed, 2 Jul 2025 23:03:49 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.44 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751497432; cv=none; b=sQgFgLSP7tanr2IHB0hsDJmZxWDQ6Cei9vEBB3q2QVCisvTgA1OhPQrlup3nJFpt5Pc6mCnDdzzhN9OVScPoTiybVoAh2E9DITKuDkjmFUbyJHrYG8gmGfl5tl+A6BQKp3T9Upfef8HctRNxEfzwEHgvKnDTCiV46u8g8F8LNqk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751497432; c=relaxed/simple; bh=i9AIlqz+m2xLlmxni/uLhWEEYQzXJjtE6Fv5QhtKO5A=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version:Content-Type; b=jQ1IjQoem1iCIJIBPo3V7wqYwUaJSj4oygaUJTILGNftFF4YTluf0dM+VdDBgSb2wG16mfCFfNTfFW3NWdHdccel/kXWu2czYXYeMAW/Fjay+L6fYcxekHBg/JauXifVUXF6ccI+acL5RKl+pI6DZ6SAymTV6bGqHAE4xhFPNeM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=ZAbUGDfX; arc=none smtp.client-ip=209.85.208.44 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="ZAbUGDfX" Received: by mail-ed1-f44.google.com with SMTP id 4fb4d7f45d1cf-6095cea1f4eso809628a12.0; Wed, 02 Jul 2025 16:03:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1751497428; x=1752102228; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=0VxCB66g+rwf3bkGrki2VGfXdgvW2y+yEMxdthhJx44=; b=ZAbUGDfXWqzrgIdlmpmkC+BKNVy2V23Ot50EOHs9mrm/OVKyO+hwrAYKOrlHP8girG wHZz2r7MUpvUjeAnn1MnxZym2dW6vZaE88dVzRzt4krojgdRt4VuAfktvKobQ3VYReQu tibWtoDSmtJYKvR7gxjKMUoJyar7mHAWRVXQui25vwrOC12FYI3umOma4sM8aUP5vifb ID1uxrxz5olSMhnxqHxtOFAZEOa1hkQxVo5XpntB5VRctC2o+3cJHb7OXQ6WhA3Ugm+K EVPGNm4aL3DJtJ3fSIrjNpPSrodkZmF1zczvbEpNFiXd+ldx0nK/w5roRPvkeNZCAktP DKUw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1751497428; x=1752102228; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=0VxCB66g+rwf3bkGrki2VGfXdgvW2y+yEMxdthhJx44=; b=CMW5GkZPY4LAHJ8tW5pEZIrWTuBStGrb6FftJ0L7epndK66gs+5SaPJ5webEXI2Woc uraupYbWi+RxrlPoYO4yKHvvmQX1Hniy5FfzoVQYLaZGcZgYCr1gPn/ZxBbVCryItwci v6l3nzvxBjD+Aq3dACV13MOkCpuM/5/5E9/esA5CZomjeHfiJ6Cv3DUv1dCX0SQL5N4t JJT33HVMI9pZ8kex4WnOVvsKZQOn7JLz4cg3rXNcik8tTROvl+y/xqae6YFItl6L2y4Y K0d7FiOSCwoj2m9YHHwYOR5+I6p+NR8L+p2wTsL1wtyutHUoT81lnxLYIgS028mqKM3X oT5g== X-Forwarded-Encrypted: i=1; AJvYcCVCVgiNZoBhyTNoD6WlAWfS7CE/i3KYNrRxs4X26G2r5PFV6111Cp0QfpQZVSGSPNwinaNnMl+FkXI5kHw1@vger.kernel.org, AJvYcCVlCpL7gpYnAchQbNmIdeVuYpjQ3FgTmFzknn9MO52HocdS0zPRAY6RpxgwnB/gb8Th9nG9fKcB0Kk=@vger.kernel.org X-Gm-Message-State: AOJu0YyeQLYed6GngSiMDxgdr+xDe9fRXVL0MlJ9rvlu8cvwWcGlADy6 N5p3GZken4UaDLYgqV6zTa9AgC+EYOFDLPOX+H37sB/PtIhU2FqjBucJ X-Gm-Gg: ASbGncsuQXhTGOgVAMyEPDqFJBxUbbH+CsfPU54PiyqYUD6JHsrcJomSlML8Kh3qGjC GJJaoRhXrWw9EYHwSUxiykbWELPMZq6c5UCG+ohxPVd98+5S6IaS+GpKWlNWlO0a3rDU93UTlRZ euuUQcCkqf+z4RIAeFX2o5ahak4+wB4fD8y0T3z4bUZmFNTWK5e7W5h4bWg77CCaLZHpMQ3giCL pxU6VJVDo1GYu14z7lCSEhabTOPcgN0F/wsQ5lmZ+GMU3qRQmYPnPCDqWsU9uMXqtB2hr7QD8Q2 RkP+6Fr0a6+QiVs6P52InhDhWiWF3NPpPprYaNS+vP397n0iop8pgCbky+RVeUTtj5QprFc9t9b kvmt5SyCJ1aEE9z8toW+7z8e41HBftLRtN1F5T7oGk0Q= X-Google-Smtp-Source: AGHT+IGOsqNEcDpcgbE15ivZw/RatRj9z+nNpMaTmLtKaS95XqF2sKAOy4KT2AMo5CQSYXtiy9fsKQ== X-Received: by 2002:a05:6402:321c:b0:60c:45fe:c6de with SMTP id 4fb4d7f45d1cf-60e764fc980mr15183a12.0.1751497428034; Wed, 02 Jul 2025 16:03:48 -0700 (PDT) Received: from localhost.localdomain (84-72-156-211.dclient.hispeed.ch. [84.72.156.211]) by smtp.gmail.com with ESMTPSA id 4fb4d7f45d1cf-60c8319e706sm10031469a12.47.2025.07.02.16.03.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 02 Jul 2025 16:03:47 -0700 (PDT) From: Lothar Rubusch To: lars@metafoo.de, Michael.Hennerich@analog.com, jic23@kernel.org, dlechner@baylibre.com, nuno.sa@analog.com, andy@kernel.org, corbet@lwn.net Cc: linux-iio@vger.kernel.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, eraretuya@gmail.com, l.rubusch@gmail.com Subject: [PATCH v11 7/8] docs: iio: add documentation for adxl345 driver Date: Wed, 2 Jul 2025 23:03:14 +0000 Message-Id: <20250702230315.19297-8-l.rubusch@gmail.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250702230315.19297-1-l.rubusch@gmail.com> References: <20250702230315.19297-1-l.rubusch@gmail.com> 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 The documentation describes the ADXL345 driver, IIO interface, interface usage and configuration. Signed-off-by: Lothar Rubusch --- Documentation/iio/adxl345.rst | 418 ++++++++++++++++++++++++++++++++++ Documentation/iio/index.rst | 1 + 2 files changed, 419 insertions(+) create mode 100644 Documentation/iio/adxl345.rst diff --git a/Documentation/iio/adxl345.rst b/Documentation/iio/adxl345.rst new file mode 100644 index 000000000000..8ee01b8b87f4 --- /dev/null +++ b/Documentation/iio/adxl345.rst @@ -0,0 +1,418 @@ +.. SPDX-License-Identifier: GPL-2.0 + +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D +ADXL345 driver +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +This driver supports Analog Device's ADXL345/375 on SPI/I2C bus. + +1. Supported Devices +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +* `ADXL345 `_ +* `ADXL375 `_ + +The ADXL345 is a generic purpose low power, 3-axis accelerometer with sele= ctable +measurement ranges. The ADXL345 supports the =C2=B12 g, =C2=B14 g, =C2=B18= g, and =C2=B116 g ranges. + +2. Device Attributes +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +Each IIO device, has a device folder under ``/sys/bus/iio/devices/iio:devi= ceX``, +where X is the IIO index of the device. Under these folders reside a set of +device files, depending on the characteristics and features of the hardware +device in questions. These files are consistently generalized and document= ed in +the IIO ABI documentation. + +The following table shows the ADXL345 related device files, found in the +specific device folder path ``/sys/bus/iio/devices/iio:deviceX``. + ++-------------------------------------------+-----------------------------= -----------------------------+ +| 3-Axis Accelerometer related device files | Description = | ++-------------------------------------------+-----------------------------= -----------------------------+ +| in_accel_sampling_frequency | Currently selected sample ra= te. | ++-------------------------------------------+-----------------------------= -----------------------------+ +| in_accel_sampling_frequency_available | Available sampling frequency= configurations. | ++-------------------------------------------+-----------------------------= -----------------------------+ +| in_accel_scale | Scale/range for the accelero= meter channels. | ++-------------------------------------------+-----------------------------= -----------------------------+ +| in_accel_scale_available | Available scale ranges for t= he accelerometer channel. | ++-------------------------------------------+-----------------------------= -----------------------------+ +| in_accel_x_calibbias | Calibration offset for the X= -axis accelerometer channel. | ++-------------------------------------------+-----------------------------= -----------------------------+ +| in_accel_x_raw | Raw X-axis accelerometer cha= nnel value. | ++-------------------------------------------+-----------------------------= -----------------------------+ +| in_accel_y_calibbias | y-axis acceleration offset c= orrection | ++-------------------------------------------+-----------------------------= -----------------------------+ +| in_accel_y_raw | Raw Y-axis accelerometer cha= nnel value. | ++-------------------------------------------+-----------------------------= -----------------------------+ +| in_accel_z_calibbias | Calibration offset for the Z= -axis accelerometer channel. | ++-------------------------------------------+-----------------------------= -----------------------------+ +| in_accel_z_raw | Raw Z-axis accelerometer cha= nnel value. | ++-------------------------------------------+-----------------------------= -----------------------------+ + +Channel Processed Values +------------------------- + +A channel value can be read from its _raw attribute. The value returned is= the +raw value as reported by the devices. To get the processed value of the ch= annel, +apply the following formula: + +.. code-block:: bash + + processed value =3D (_raw + _offset) * _scale + +Where _offset and _scale are device attributes. If no _offset attribute is +present, simply assume its value is 0. + ++-------------------------------------+---------------------------+ +| Channel type | Measurement unit | ++-------------------------------------+---------------------------+ +| Acceleration on X, Y, and Z axis | Meters per second squared | ++-------------------------------------+---------------------------+ + +Sensor Events +------------- + +Specific IIO events are triggered by their corresponding interrupts. The s= ensor +driver supports either none or a single active interrupt (INT) line, selec= table +from the two available options: INT1 or INT2. The active INT line should be +specified in the device tree. If no INT line is configured, the sensor def= aults +to FIFO bypass mode, where event detection is disabled and only X, Y, and = Z axis +measurements are available. + +The table below lists the ADXL345-related device files located in the +device-specific path: ``/sys/bus/iio/devices/iio:deviceX/events``. +Note that activity and inactivity detection are DC-coupled by default; +therefore, only the AC-coupled activity and inactivity events are explicit= ly +listed. + ++---------------------------------------------+---------------------------= ------------------+ +| Event handle | Description = | ++---------------------------------------------+---------------------------= ------------------+ +| in_accel_gesture_doubletap_en | Enable double tap detectio= n on all axis | ++---------------------------------------------+---------------------------= ------------------+ +| in_accel_gesture_doubletap_reset_timeout | Double tap window in [us] = | ++---------------------------------------------+---------------------------= ------------------+ +| in_accel_gesture_doubletap_tap2_min_delay | Double tap latent in [us] = | ++---------------------------------------------+---------------------------= ------------------+ +| in_accel_gesture_singletap_timeout | Single tap duration in [us= ] | ++---------------------------------------------+---------------------------= ------------------+ +| in_accel_gesture_singletap_value | Single tap threshold value= in 62.5/LSB | ++---------------------------------------------+---------------------------= ------------------+ +| in_accel_mag_falling_period | Inactivity time in seconds= | ++---------------------------------------------+---------------------------= ------------------+ +| in_accel_mag_falling_value | Inactivity threshold value= in 62.5/LSB | ++---------------------------------------------+---------------------------= ------------------+ +| in_accel_mag_adaptive_rising_en | Enable AC coupled activity= on X axis | ++---------------------------------------------+---------------------------= ------------------+ +| in_accel_mag_adaptive_falling_period | AC coupled inactivity time= in seconds | ++---------------------------------------------+---------------------------= ------------------+ +| in_accel_mag_adaptive_falling_value | AC coupled inactivity thre= shold in 62.5/LSB | ++---------------------------------------------+---------------------------= ------------------+ +| in_accel_mag_adaptive_rising_value | AC coupled activity thresh= old in 62.5/LSB | ++---------------------------------------------+---------------------------= ------------------+ +| in_accel_mag_rising_en | Enable activity detection = on X axis | ++---------------------------------------------+---------------------------= ------------------+ +| in_accel_mag_rising_value | Activity threshold value i= n 62.5/LSB | ++---------------------------------------------+---------------------------= ------------------+ +| in_accel_x_gesture_singletap_en | Enable single tap detectio= n on X axis | ++---------------------------------------------+---------------------------= ------------------+ +| in_accel_x&y&z_mag_falling_en | Enable inactivity detectio= n on all axis | ++---------------------------------------------+---------------------------= ------------------+ +| in_accel_x&y&z_mag_adaptive_falling_en | Enable AC coupled inactivi= ty on all axis | ++---------------------------------------------+---------------------------= ------------------+ +| in_accel_y_gesture_singletap_en | Enable single tap detectio= n on Y axis | ++---------------------------------------------+---------------------------= ------------------+ +| in_accel_z_gesture_singletap_en | Enable single tap detectio= n on Z axis | ++---------------------------------------------+---------------------------= ------------------+ + +Please refer to the sensor's datasheet for a detailed description of this +functionality. + +Manually setting the **ODR** will cause the driver to estimate default val= ues +for inactivity detection timing, where higher ODR values correspond to lon= ger +default wait times, and lower ODR values to shorter ones. If these default= s do +not meet your application=E2=80=99s needs, you can explicitly configure th= e inactivity +wait time. Setting this value to 0 will revert to the default behavior. + +When changing the **g range** configuration, the driver attempts to estima= te +appropriate activity and inactivity thresholds by scaling the default valu= es +based on the ratio of the previous range to the new one. The resulting thr= eshold +will never be zero and will always fall between 1 and 255, corresponding t= o up +to 62.5=E2=80=AFg/LSB as specified in the datasheet. However, you can over= ride these +estimated thresholds by setting explicit values. + +When **activity** and **inactivity** events are enabled, the driver +automatically manages hysteresis behavior by setting the **link** and +**auto-sleep** bits. The link bit connects the activity and inactivity +functions, so that one follows the other. The auto-sleep function puts the +sensor into sleep mode when inactivity is detected, reducing power consump= tion +to the sub-12.5=E2=80=AFHz rate. + +In DC-coupled mode, the current acceleration magnitude is directly compare= d to +the values in the THRESH_ACT and THRESH_INACT registers to determine activ= ity or +inactivity. In contrast, AC-coupled activity detection uses the accelerati= on +value at the start of detection as a reference point, and subsequent sampl= es are +compared against this reference. While DC-coupling is the default mode-com= paring +live values to fixed thresholds-AC-coupling relies on an internal filter +relative to the configured threshold. + +AC and DC coupling modes are configured separately for activity and inacti= vity +detection, but only one mode can be active at a time for each. For example= , if +AC-coupled activity detection is enabled and then DC-coupled mode is set, = only +DC-coupled activity detection will be active. In other words, only the most +recent configuration is applied. + +**Single tap** detection can be configured per the datasheet by setting the +threshold and duration parameters. When only single tap detection is enabl= ed, +the single tap interrupt triggers as soon as the acceleration exceeds the +threshold (marking the start of the duration) and then falls below it, pro= vided +the duration limit is not exceeded. If both single tap and double tap dete= ctions +are enabled, the single tap interrupt is triggered only after the double t= ap +event has been either confirmed or dismissed. + +To configure **double tap** detection, you must also set the window and la= tency +parameters in microseconds (=C2=B5s). The latency period begins once the s= ingle tap +signal drops below the threshold and acts as a waiting time during which a= ny +spikes are ignored for double tap detection. After the latency period ends= , the +detection window starts. If the acceleration rises above the threshold and= then +falls below it again within this window, a double tap event is triggered u= pon +the fall below the threshold. + +Double tap event detection is thoroughly explained in the datasheet. After= a +single tap event is detected, a double tap event may follow, provided the = signal +meets certain criteria. However, double tap detection can be invalidated f= or +three reasons: + +* If the **suppress bit** is set, any acceleration spike above the tap + threshold during the tap latency period immediately invalidates the doub= le tap + detection. In other words, no spikes are allowed during latency when the + suppress bit is active. + +* The double tap event is invalid if the acceleration is above the thresho= ld at + the start of the double tap window. + +* Double tap detection is also invalidated if the acceleration duration ex= ceeds + the limit set by the duration register. + +For double tap detection, the same duration applies as for single tap: the +acceleration must rise above the threshold and then fall below it within t= he +specified duration. Note that the suppress bit is typically enabled when d= ouble +tap detection is active. + +Usage Examples +-------------- + +Show device name: + +.. code-block:: bash + + root:/sys/bus/iio/devices/iio:device0> cat name + adxl345 + +Show accelerometer channels value: + +.. code-block:: bash + + root:/sys/bus/iio/devices/iio:device0> cat in_accel_x_raw + -1 + root:/sys/bus/iio/devices/iio:device0> cat in_accel_y_raw + 2 + root:/sys/bus/iio/devices/iio:device0> cat in_accel_z_raw + -253 + +Set calibration offset for accelerometer channels: + +.. code-block:: bash + + root:/sys/bus/iio/devices/iio:device0> cat in_accel_x_calibbias + 0 + + root:/sys/bus/iio/devices/iio:device0> echo 50 > in_accel_x_calibb= ias + root:/sys/bus/iio/devices/iio:device0> cat in_accel_x_calibbias + 50 + +Given the 13-bit full resolution, the available ranges are calculated by t= he +following formula: + +.. code-block:: bash + + (g * 2 * 9.80665) / (2^(resolution) - 1) * 100; for g :=3D 2|4|8|16 + +Scale range configuration: + +.. code-block:: bash + + root:/sys/bus/iio/devices/iio:device0> cat ./in_accel_scale + 0.478899 + root:/sys/bus/iio/devices/iio:device0> cat ./in_accel_scale_availa= ble + 0.478899 0.957798 1.915595 3.831190 + + root:/sys/bus/iio/devices/iio:device0> echo 1.915595 > ./in_accel_= scale + root:/sys/bus/iio/devices/iio:device0> cat ./in_accel_scale + 1.915595 + +Set output data rate (ODR): + +.. code-block:: bash + + root:/sys/bus/iio/devices/iio:device0> cat ./in_accel_sampling_fre= quency + 200.000000 + + root:/sys/bus/iio/devices/iio:device0> cat ./in_accel_sampling_fre= quency_available + 0.097000 0.195000 0.390000 0.781000 1.562000 3.125000 6.250000 12.= 500000 25.000000 50.000000 100.000000 200.000000 400.000000 800.000000 1600= .000000 3200.000000 + + root:/sys/bus/iio/devices/iio:device0> echo 1.562000 > ./in_accel_= sampling_frequency + root:/sys/bus/iio/devices/iio:device0> cat ./in_accel_sampling_fre= quency + 1.562000 + +Configure one or several events: + +.. code-block:: bash + + root:> cd /sys/bus/iio/devices/iio:device0 + + root:/sys/bus/iio/devices/iio:device0> echo 1 > ./buffer0/in_accel= _x_en + root:/sys/bus/iio/devices/iio:device0> echo 1 > ./buffer0/in_accel= _y_en + root:/sys/bus/iio/devices/iio:device0> echo 1 > ./buffer0/in_accel= _z_en + + root:/sys/bus/iio/devices/iio:device0> echo 1 > ./scan_elements/in= _accel_x_en + root:/sys/bus/iio/devices/iio:device0> echo 1 > ./scan_elements/in= _accel_y_en + root:/sys/bus/iio/devices/iio:device0> echo 1 > ./scan_elements/in= _accel_z_en + + root:/sys/bus/iio/devices/iio:device0> echo 14 > ./in_accel_x_ca= libbias + root:/sys/bus/iio/devices/iio:device0> echo 2 > ./in_accel_y_ca= libbias + root:/sys/bus/iio/devices/iio:device0> echo -250 > ./in_accel_z_ca= libbias + + root:/sys/bus/iio/devices/iio:device0> echo 24 > ./buffer0/length + + ## AC coupled activity, threshold [62.5/LSB] + root:/sys/bus/iio/devices/iio:device0> echo 6 > ./events/in_accel_= mag_adaptive_rising_value + + ## AC coupled inactivity, threshold, [62.5/LSB] + root:/sys/bus/iio/devices/iio:device0> echo 4 > ./events/in_accel_= mag_adaptive_falling_value + + ## AC coupled inactivity, time [s] + root:/sys/bus/iio/devices/iio:device0> echo 3 > ./events/in_accel_= mag_adaptive_falling_period + + ## singletap, threshold + root:/sys/bus/iio/devices/iio:device0> echo 35 > ./events/in_accel= _gesture_singletap_value + + ## singletap, duration [us] + root:/sys/bus/iio/devices/iio:device0> echo 0.001875 > ./events/i= n_accel_gesture_singletap_timeout + + ## doubletap, window [us] + root:/sys/bus/iio/devices/iio:device0> echo 0.025 > ./events/in_ac= cel_gesture_doubletap_reset_timeout + + ## doubletap, latent [us] + root:/sys/bus/iio/devices/iio:device0> echo 0.025 > ./events/in_ac= cel_gesture_doubletap_tap2_min_delay + + ## AC coupled activity, enable + root:/sys/bus/iio/devices/iio:device0> echo 1 > ./events/in_accel_= mag_adaptive_rising_en + + ## AC coupled inactivity, enable + root:/sys/bus/iio/devices/iio:device0> echo 1 > ./events/in_accel_= x\&y\&z_mag_adaptive_falling_en + + ## singletap, enable + root:/sys/bus/iio/devices/iio:device0> echo 1 > ./events/in_accel_= x_gesture_singletap_en + root:/sys/bus/iio/devices/iio:device0> echo 1 > ./events/in_accel_= y_gesture_singletap_en + root:/sys/bus/iio/devices/iio:device0> echo 1 > ./events/in_accel_= z_gesture_singletap_en + + ## doubletap, enable + root:/sys/bus/iio/devices/iio:device0> echo 1 > ./events/in_accel_= gesture_doubletap_en + +Verify incoming events: + +.. code-block:: bash + + root:# iio_event_monitor adxl345 + Found IIO device with name adxl345 with device number 0 + Event: time: 1739063415957073383, type: accel(z), channel: 0, evty= pe: mag, direction: rising + Event: time: 1739063415963770218, type: accel(z), channel: 0, evty= pe: mag, direction: rising + Event: time: 1739063416002563061, type: accel(z), channel: 0, evty= pe: gesture, direction: singletap + Event: time: 1739063426271128739, type: accel(x&y&z), channel: 0, = evtype: mag, direction: falling + Event: time: 1739063436539080713, type: accel(x&y&z), channel: 0, = evtype: mag, direction: falling + Event: time: 1739063438357970381, type: accel(z), channel: 0, evty= pe: mag, direction: rising + Event: time: 1739063446726161586, type: accel(z), channel: 0, evty= pe: mag, direction: rising + Event: time: 1739063446727892670, type: accel(z), channel: 0, evty= pe: mag, direction: rising + Event: time: 1739063446743019768, type: accel(z), channel: 0, evty= pe: mag, direction: rising + Event: time: 1739063446744650696, type: accel(z), channel: 0, evty= pe: mag, direction: rising + Event: time: 1739063446763559386, type: accel(z), channel: 0, evty= pe: gesture, direction: singletap + Event: time: 1739063448818126480, type: accel(x&y&z), channel: 0, = evtype: mag, direction: falling + ... + +Activity and inactivity belong together and indicate state changes as foll= ows + +.. code-block:: bash + + root:# iio_event_monitor adxl345 + Found IIO device with name adxl345 with device number 0 + Event: time: 1744648001133946293, type: accel(x), channel: 0, evty= pe: mag, direction: rising + + Event: time: 1744648057724775499, type: accel(x&y&z), channel: 0, = evtype: mag, direction: falling + ... + +3. Device Buffers +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +This driver supports IIO buffers. + +All devices support retrieving the raw acceleration and temperature measur= ements +using buffers. + +Usage examples +-------------- + +Select channels for buffer read: + +.. code-block:: bash + + root:/sys/bus/iio/devices/iio:device0> echo 1 > scan_elements/in_a= ccel_x_en + root:/sys/bus/iio/devices/iio:device0> echo 1 > scan_elements/in_a= ccel_y_en + root:/sys/bus/iio/devices/iio:device0> echo 1 > scan_elements/in_a= ccel_z_en + +Set the number of samples to be stored in the buffer: + +.. code-block:: bash + + root:/sys/bus/iio/devices/iio:device0> echo 10 > buffer/length + +Enable buffer readings: + +.. code-block:: bash + + root:/sys/bus/iio/devices/iio:device0> echo 1 > buffer/enable + +Obtain buffered data: + +.. code-block:: bash + + root:> iio_readdev -b 16 -s 1024 adxl345 | hexdump -d + WARNING: High-speed mode not enabled + 0000000 00003 00012 00013 00005 00010 00011 00005 = 00011 + 0000010 00013 00004 00012 00011 00003 00012 00014 = 00007 + 0000020 00011 00013 00004 00013 00014 00003 00012 = 00013 + 0000030 00004 00012 00013 00005 00011 00011 00005 = 00012 + 0000040 00014 00005 00012 00014 00004 00010 00012 = 00004 + 0000050 00013 00011 00003 00011 00012 00005 00011 = 00013 + 0000060 00003 00012 00012 00003 00012 00012 00004 = 00012 + 0000070 00012 00003 00013 00013 00003 00013 00012 = 00005 + 0000080 00012 00013 00003 00011 00012 00005 00012 = 00013 + 0000090 00003 00013 00011 00005 00013 00014 00003 = 00012 + 00000a0 00012 00003 00012 00013 00004 00012 00015 = 00004 + 00000b0 00014 00011 00003 00014 00013 00004 00012 = 00011 + 00000c0 00004 00012 00013 00004 00014 00011 00004 = 00013 + 00000d0 00012 00002 00014 00012 00005 00012 00013 = 00005 + 00000e0 00013 00013 00003 00013 00013 00005 00012 = 00013 + 00000f0 00004 00014 00015 00005 00012 00011 00005 = 00012 + ... + +See ``Documentation/iio/iio_devbuf.rst`` for more information about how bu= ffered +data is structured. + +4. IIO Interfacing Tools +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +See ``Documentation/iio/iio_tools.rst`` for the description of the availab= le IIO +interfacing tools. diff --git a/Documentation/iio/index.rst b/Documentation/iio/index.rst index 2d6afc5a8ed5..c333720c1c9f 100644 --- a/Documentation/iio/index.rst +++ b/Documentation/iio/index.rst @@ -32,6 +32,7 @@ Industrial I/O Kernel Drivers adis16480 adis16550 adxl380 + adxl345 bno055 ep93xx_adc opt4060 --=20 2.39.5 From nobody Wed Oct 8 02:17:15 2025 Received: from mail-ed1-f49.google.com (mail-ed1-f49.google.com [209.85.208.49]) (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 14FC22F85DF; Wed, 2 Jul 2025 23:03:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.49 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751497433; cv=none; b=tbhDAkYrt8Jtd/Sp740GaQLxEKwXy3OnzmJcQrPa7fL/nDNHt2pOHQZ+VtQJxQ6XQjiqu3tRZxJ6vnaz3c3jJ29wDiGRSqqwSwrCFq++RK4hkwT5OcZxGL4kR/5Yjqc/1gG5V+1N0jwTNp3U7Vdgr4Z6uIRqghn8LunJvce5tPA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751497433; c=relaxed/simple; bh=2oCKa77MmvtjuzTFUyhx2spEW5JEAkYP0TnixHDrvQ0=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version:Content-Type; b=UNpu+lJQPok2aty5RXNQpsBxLXP6e+7DtMEFQRQ49qCF/dAEyqoadkORCcoZAMBF8E5HQjFVgnK+8D18APe/aZfwOC+j9twKJsy8hKTs3dr+sWCSb8sPuETUW1byydcYvbE2kIYJzpugoj/CfvOZZp/az0ah7rEjP9rDtZw4SyY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=h6wMVUBN; arc=none smtp.client-ip=209.85.208.49 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="h6wMVUBN" Received: by mail-ed1-f49.google.com with SMTP id 4fb4d7f45d1cf-607780f0793so1519562a12.2; Wed, 02 Jul 2025 16:03:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1751497430; x=1752102230; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=JSMGUq00Wscsa5i+rwtOnSrfeZI1fF8spFiZz7cfc/s=; b=h6wMVUBNKVE9ozZeXwb24Gt00oOBzlDo2x9jzINsHLymSym2HaHt8MDD+yqjjO1RzV prnRwm6tzchVDUWS46QIcA8M5pgBnq1vVZCAy1fpFBwXzoTLIgTQEISIPFMOlhFqRRdy AhMGexdKpDsJZV6AwiEDqZlTdDoHq2kjHTQsLFz4w/hmVozFsQZvoj95gHm8JuECKR0G cGCPHnU8xj5DQoUGNz27dK4OvvHjc8S6e0sVor70OH6dBr1mlS+2N0H2PB9qaHud6CbN n3q4iyLFoEM6nN2n2AneFGD5xO/DZEBhoOjIWxq8v8wICzHTYAZBzSAhL9O4BQ8SsVEq OAaQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1751497430; x=1752102230; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=JSMGUq00Wscsa5i+rwtOnSrfeZI1fF8spFiZz7cfc/s=; b=fA9/FCB2tdw8g3BQB3+hz+g7bm8XFw/aL+u1cqed6lWhk3Bti/Wu6HIGuUolz6RcpR EUPcXzM099D4I07rojtdrz5TUwmVI5Uj+9B5yKbRi+iZ+RFBk01z+XOaOcmqVSoz2Jex S2AyYKLNvj3oYivdtOgkEq7Yzl3FaTAjyvv/xvwt7REf5XbHfM7yp2GwPrQ9E2xz6jMD g0MI1tPOv7MrZRzPNOZ1OfceN6N84byFCEqMDdKSiUI3JVSvYLYAoddIRYfPb2L4i2yB iO8aRAJdrFIdA5Sgay0+WF7PwPRR2vIXv7OHlmqR57NzmZc3kiC/cy8vRVhOJFuYqHqB lmFQ== X-Forwarded-Encrypted: i=1; AJvYcCWUXO6owm2dv9OXcNyHEBjAJbK4MFKVJoiDG/CtMv3XSSbn284RJaJGRfIoAYFzVuwMhII4cJ2ZRtc=@vger.kernel.org, AJvYcCXagHfJid48neSqvXEtbeWI8hrvioWZNx7Zh7QdZzZAfv5g3jOImiZF0uVJB6HYLNTxybDSYyPnOuOHeKsE@vger.kernel.org X-Gm-Message-State: AOJu0Yyzoh/A0RHhUhMUF9ljj+vgaestwLYVwjPqHAXX2l49OVj5uOfX na4LWCw6m2zswk9glaqwzL8FEMCy7HD+ji3ylN714iFM8QIHz/C2IkE/ X-Gm-Gg: ASbGnct8uTYSNoA9gAS36/koB6YWfQ6gVlm6hLYMA1U30QGywLXe+pQwpp119XgTdIm f0EuvTzMKrXlEJ7/NO0ziSuwfug7FTf3Fx40HjhpOO9P0F+vLTCVTO+/rOYZ80WWwdor4aD/bqZ 9u5flWXokKmaTSrIoECqW3Q/7SnsjXQs9OAF71xsBJjWkIChdiXxfoQ/OhWtj0vR+o3DLj2yZXM AcA8oKAfX509L2PLRmiJkO7t6EbgQ/24ajqIUhVrIr9CMwB4HegCx07POdY2wH2Ib1PaUGhYH3b mTmHctEL9ZT6Ln4xnVTsg2r8qhtmc6Dp0ek+4pCUuj/TyNNn12tMoCCzO8YNr1yAYC3kc/PKspM lTGXx8YWXLe3d7kEutWb160deWripgj0eP7l61GNHZyw= X-Google-Smtp-Source: AGHT+IE3HM/yk20/T+LgFmKx7sguDxopwCTI+CHO3W59kYUljAIEQBTlUvCK+ZgLTeBaGo4TuhgiKg== X-Received: by 2002:a05:6402:1914:b0:609:a671:ebb9 with SMTP id 4fb4d7f45d1cf-60e52cd6d6dmr1208843a12.5.1751497430072; Wed, 02 Jul 2025 16:03:50 -0700 (PDT) Received: from localhost.localdomain (84-72-156-211.dclient.hispeed.ch. [84.72.156.211]) by smtp.gmail.com with ESMTPSA id 4fb4d7f45d1cf-60c8319e706sm10031469a12.47.2025.07.02.16.03.48 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 02 Jul 2025 16:03:49 -0700 (PDT) From: Lothar Rubusch To: lars@metafoo.de, Michael.Hennerich@analog.com, jic23@kernel.org, dlechner@baylibre.com, nuno.sa@analog.com, andy@kernel.org, corbet@lwn.net Cc: linux-iio@vger.kernel.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, eraretuya@gmail.com, l.rubusch@gmail.com Subject: [PATCH v11 8/8] docs: iio: describe inactivity and free-fall detection on the ADXL345 Date: Wed, 2 Jul 2025 23:03:15 +0000 Message-Id: <20250702230315.19297-9-l.rubusch@gmail.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250702230315.19297-1-l.rubusch@gmail.com> References: <20250702230315.19297-1-l.rubusch@gmail.com> 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 Describe the inactivity detection additionally using the free-fall register. Due to the controversial discussions on the mailing list, this section of the documentation will be committed separately to allow for a more focused and detailed elaboration of the topic. Signed-off-by: Lothar Rubusch --- Documentation/iio/adxl345.rst | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/Documentation/iio/adxl345.rst b/Documentation/iio/adxl345.rst index 8ee01b8b87f4..c5525267ea12 100644 --- a/Documentation/iio/adxl345.rst +++ b/Documentation/iio/adxl345.rst @@ -150,6 +150,31 @@ functions, so that one follows the other. The auto-sle= ep function puts the sensor into sleep mode when inactivity is detected, reducing power consump= tion to the sub-12.5=E2=80=AFHz rate. =20 +The inactivity time is configurable between 1 and 255 seconds. In addition= to +inactivity detection, the sensor also supports free-fall detection, which,= from +the IIO perspective, is treated as a fall in magnitude across all axes. In +sensor terms, free-fall is defined using an inactivity period ranging from= 0.000 +to 1.000 seconds. + +The driver behaves as follows: +* If the configured inactivity period is 1 second or more, the driver uses= the + sensor's inactivity register. This allows the event to be linked with + activity detection, use auto-sleep, and be either AC- or DC-coupled. + +* If the inactivity period is less than 1 second, the event is treated as = plain + inactivity or free-fall detection. In this case, auto-sleep and coupling + (AC/DC) are not applied. + +* If an inactivity time of 0 seconds is configured, the driver selects a + heuristically determined default period (greater than 1 second) to optim= ize + power consumption. This also uses the inactivity register. + +Note: It is recommended to use the activity, inactivity, or free-fall regi= sters +when operating with an ODR between 12.5=E2=80=AFHz and 400=E2=80=AFHz. Acc= ording to the +datasheet, the recommended free-fall threshold is between 300=E2=80=AFmg a= nd 600=E2=80=AFmg +(register values 0x05 to 0x09), and the suggested free-fall time ranges fr= om +100=E2=80=AFms to 350=E2=80=AFms (register values 0x14 to 0x46). + In DC-coupled mode, the current acceleration magnitude is directly compare= d to the values in the THRESH_ACT and THRESH_INACT registers to determine activ= ity or inactivity. In contrast, AC-coupled activity detection uses the accelerati= on --=20 2.39.5