From patchwork Tue Mar 18 23:08:33 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lothar Rubusch X-Patchwork-Id: 14021714 Received: from mail-wr1-f53.google.com (mail-wr1-f53.google.com [209.85.221.53]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 206C7207A3A; Tue, 18 Mar 2025 23:08:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.53 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742339338; cv=none; b=kwreeMUFbDXxEiUWcQ+6tWH1b7zriprp7DmUvdohGQG2N5yzvAdxA3aFnParRds7r4HwLuVzKZC6UgurWpcAC49zeU8MA31IUgfJfxybwFrL+Sz40XwcK+UBxEdKxHjOUdbOepDxgp9DQ6Wl46avhLYXU0uM+to+UFdSs3Pz9+k= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742339338; c=relaxed/simple; bh=fM3+KC/UZ31kXPGTb5S0rsSfrRmlbZY6btYAdurQouc=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=nz70JJrihqHlNpbaMX0mjh8IpEPbrtSMkuL3pfAa6ig/wGpF2o9Qdvxp0A3bhUgZ6MHR+0i7b2Y0vU3Iv2EcrbFgNp86e/9XrwY7yIV3E5GChYhrrQqFPuEKlMeCoIQmchpQDeFW6gHWZjW+M9NweGSu1+qr+xqHyA2GlR8jhWM= 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=jZkZYhhm; arc=none smtp.client-ip=209.85.221.53 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="jZkZYhhm" Received: by mail-wr1-f53.google.com with SMTP id ffacd0b85a97d-3912ebb8e88so839947f8f.0; Tue, 18 Mar 2025 16:08:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1742339335; x=1742944135; 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=yL1NluBLKnVOXTYYd19e7pbv7E9LsYXKQXHoL8wk6rg=; b=jZkZYhhmNyInlHST860hhu6ylDz8Y3OHSTtbS15/kow27vPkqDUj0djdBtpd/ErtUb z4FQOggzjNhNg94UbFGFtJaFxOi3NLZ/MJDoqJ3rcG8ZHMQL3uOY4EKvEHyr1qKB8AUk gIBRSryj0YvyiGsqZBuLFX1USEzYIsXTpp3//XbrERQNP09ydAHuD5nCHQc9N/6LvzMx ozIDL73Y34LwU9zROEPPSLHimxnQZx859EVrP+RQoaXzibCuwoah/NwPhAzNspcae81E O1PgxtAfYAXMG/67Rake1Ukb/MJqKjkUHFFuSx/XJM0ZkJe7rvqjGS+Btt9bit7SrANm XOrw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1742339335; x=1742944135; 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=yL1NluBLKnVOXTYYd19e7pbv7E9LsYXKQXHoL8wk6rg=; b=wPjLzTy3DGYSGIwrHvUbZZeEYRzbHCHKf99bDiMGiDUwiC1YfiWVpGQQnPpAEGdksM KtwdOstvxNusWyk/sppoBG2pffuoUppjT1Mau928j3pFeReaVig2+BiszvyM5HFQ5W/5 K+Ub/dH/GTMjPVG3nmtQRaFO4Ki5MRvDA4TcVzVExdnQI36p4GK8jUmh+eskGcjcYJiR hnZeHWbC97GnbmlJFP80WP+pxETnnmWOVj2iDZ5dzclMmkTRpX5OlBDkC3a07NtMaYP/ 6Mvqzyv1jTPs+US1HSMbnRly6DT/asu2ltbJl2+JTPJ5DfLeJw8OnDCh+iTRDEW9Kxcl 0hpg== X-Forwarded-Encrypted: i=1; AJvYcCXc6+xPQl8INRPtddz2O9WUmSq7d3E2oIKeJ5lkHnKtg/HfW8hahGOXPDntLA8eHuEfasHv0ZZGyVERUts=@vger.kernel.org X-Gm-Message-State: AOJu0YwCQljSABa44sZvGoLkhGEaoHa+w+hY0gvH+Z1jXJDLLhSGwSfg 3CnIV0l5a2jWdDHAGHzJng+vAwW2aTE48XyT2LxIWxitOP5ln3MN X-Gm-Gg: ASbGncucqfudYAgOrinEzA3Dc67zfNyyFuuGOIW4hjZLlMMsHA+GNvdg0CfIuyTXC5T WCv8vjfooCwEER66emTg0wjmnOU9OuTZeNjGnZsaghSYj5QybvtDn5EUBHlLq1Hvgv/JXtgsgLx P7xw+Q+VCYYcrMEcYiVdPWBB3YBBlPAB8chJ3M7YMfh+1c4L0nLvjOSpqLMudeQZu/hgj/0EKHA 0bJvdXl4gnZEE/mmGLSa+05WwF/5vyrCAOQi4HO6QROSSlbVMkK4yzsNsqfWJQBWdEmMhhBHub9 ERNZnOwG7IO4bVt7yQWMYJjSkoIxvl8YpS79UZbVugFxvw/auNozUL74RfF5BFDbaTFfraRB441 ufFJKQBmHiYQYg4umHq5R/QA= X-Google-Smtp-Source: AGHT+IH28s3Q9PxrRlA0g5h6AlhKffP4S7eRBc+J04iyS3O3vq2Feu1VNoRmsobYiDGkTvXom+mzfA== X-Received: by 2002:a05:600c:5250:b0:43d:301b:5508 with SMTP id 5b1f17b1804b1-43d43782e4cmr1113115e9.2.1742339335217; Tue, 18 Mar 2025 16:08:55 -0700 (PDT) Received: from 0e1b0684397b.v.cablecom.net (84-72-156-211.dclient.hispeed.ch. [84.72.156.211]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-43d440ed793sm1113455e9.39.2025.03.18.16.08.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 18 Mar 2025 16:08:54 -0700 (PDT) From: Lothar Rubusch To: lars@metafoo.de, Michael.Hennerich@analog.com, jic23@kernel.org Cc: linux-iio@vger.kernel.org, linux-kernel@vger.kernel.org, eraretuya@gmail.com, l.rubusch@gmail.com Subject: [PATCH v5 01/11] iio: accel: adxl345: introduce adxl345_push_event function Date: Tue, 18 Mar 2025 23:08:33 +0000 Message-Id: <20250318230843.76068-2-l.rubusch@gmail.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250318230843.76068-1-l.rubusch@gmail.com> References: <20250318230843.76068-1-l.rubusch@gmail.com> Precedence: bulk X-Mailing-List: linux-iio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Move the fifo handling into a separate function. This is a preparation for a generic handling of the interrupt status register results. The function is supposed to handle particular sensor events, and later to forward them to the iio channel. This is needed to read out the interrupt status register. The function shall return occurring errors, if any, or 0 in case of handled events or read fifo content. Thus migrate fifo read-out and push fifo content to iio channels into this function to be built up with additional event handling. Signed-off-by: Lothar Rubusch --- drivers/iio/accel/adxl345_core.c | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/drivers/iio/accel/adxl345_core.c b/drivers/iio/accel/adxl345_core.c index 1b4d9e60c87d..a98fb7fc748e 100644 --- a/drivers/iio/accel/adxl345_core.c +++ b/drivers/iio/accel/adxl345_core.c @@ -416,6 +416,23 @@ static int adxl345_fifo_push(struct iio_dev *indio_dev, return 0; } +static int adxl345_push_event(struct iio_dev *indio_dev, int int_stat) +{ + struct adxl345_state *st = iio_priv(indio_dev); + int samples; + + if (FIELD_GET(ADXL345_INT_WATERMARK, int_stat)) { + samples = adxl345_get_samples(st); + if (samples < 0) + return -EINVAL; + + if (adxl345_fifo_push(indio_dev, samples) < 0) + return -EINVAL; + } + + return 0; +} + /** * adxl345_irq_handler() - Handle irqs of the ADXL345. * @irq: The irq being handled. @@ -428,19 +445,12 @@ static irqreturn_t adxl345_irq_handler(int irq, void *p) struct iio_dev *indio_dev = p; struct adxl345_state *st = iio_priv(indio_dev); int int_stat; - int samples; if (regmap_read(st->regmap, ADXL345_REG_INT_SOURCE, &int_stat)) return IRQ_NONE; - if (FIELD_GET(ADXL345_INT_WATERMARK, int_stat)) { - samples = adxl345_get_samples(st); - if (samples < 0) - goto err; - - if (adxl345_fifo_push(indio_dev, samples) < 0) - goto err; - } + if (adxl345_push_event(indio_dev, int_stat)) + goto err; if (FIELD_GET(ADXL345_INT_OVERRUN, int_stat)) goto err; From patchwork Tue Mar 18 23:08:34 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lothar Rubusch X-Patchwork-Id: 14021715 Received: from mail-wm1-f45.google.com (mail-wm1-f45.google.com [209.85.128.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 99E1F211710; Tue, 18 Mar 2025 23:08:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.45 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742339340; cv=none; b=hCiMK1ZFommRifwPQyvtRQThlz4DzdamR73W11BaM49n2aAK5pOMOEdznoQOcPa89GiJiVkDGDXitLZ5VZxcjqLIStB7pcBnE7Z5/2JUxkEhMiQhj3paMLrzIvBISqEYp8wF6aovExMIHf0+U86HqxoRn7OEnWZgm0lC8AG9Q7c= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742339340; c=relaxed/simple; bh=y5IslAqmDg4mdxKMOO+rul3SuVDj/fCUEloCSsCaerQ=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=HCfVrYAbGtSxNqoZukVv5mZ8DMEXft9twGdMc1UAEVopzerk2UmdRJ96fzLo9KQcRaPLEnaS42P9A6ys1aX0c275IYH7nsT4GBo8eFRqKDveycUufJnBSIzGmlm8qB7nKooFRiwjH/PuKo8Bhpjxeo+aUdheO0BVCL0OTzdIsDc= 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=RsGgOziz; arc=none smtp.client-ip=209.85.128.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="RsGgOziz" Received: by mail-wm1-f45.google.com with SMTP id 5b1f17b1804b1-43d16a01deaso1526445e9.2; Tue, 18 Mar 2025 16:08:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1742339337; x=1742944137; 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=IMHfkz9v2A2q1ZtzvI5rEiKtpOSbE1j3RQynQq8gEew=; b=RsGgOzizkpEnjZbNWff0Oms7QIhrpd5KgJnqdqOUdb3bTxnkAFMDjNz5uoc4oTTSZY PNDQxZvXtllfRslCgJ29iPCq3+i/FuWtTCEW1Jao6VNF4Mk/UOmSquj84BcD3yroZdRK mfAMVe4rVbEYZiTXuEAg9Fwgb13v5OCa30AbuE6njlgYKYAEPu0fVJ7BVxmkq7zTgQJd YvtekrlaLAOaDaX30HwDFSC3Q2a4sAjRrVKxHZ6njoGi4x86QaQa3jDWOx7zvSecd7Qv snUUTn+d9PXyrQVbHx4s+nJoTZgvT1JK1oPd/lLvfiDkDG4hsoI9PSVAErI1mKed6oB1 zpgA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1742339337; x=1742944137; 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=IMHfkz9v2A2q1ZtzvI5rEiKtpOSbE1j3RQynQq8gEew=; b=mXfA+WJXJsP8y9mvEr0E3rE1BGFvk7zrBvz1HCLkNGZ/MGMQEwfsZWk0YonnCdRzld 4/BB++pXsNt8v6+4HPYvax3Wl5mUYYQHzkb8vViihtE6x0lIqMdA4TGV/rIYieuWiSyp MXitOiIqk5/Z3wq89GLB4flZEn/Rprav8FO18vA5qeAEJ81M8EZo/PbGhCo36JQ+qheq /FOsQdpwCjz3Y7TMnH4ZUBKJ1M0iphHw4mmTB/K/D0AdZ2BVM4PL3joCKHVHRjQBUq/t k3fE0RFGG9frwoB0tcLCEK6ak1lGalUiM78Wb+2dMsuBVfw9FMyuMXsdvR1yPiy2aPpA OrjA== X-Forwarded-Encrypted: i=1; AJvYcCWVd13sPzwaR/eYJ5wR/z01vkwPjfIRrRO4/GniH6i/TZ/nLX+um8rnDnYsHFc0dleJBJBQrAZ+DO2mUeI=@vger.kernel.org X-Gm-Message-State: AOJu0Yw7xSjzJJ5ViIZhVoxHDSf1+xq6RZvon+wVYF/0hhrf9KDqUoT/ wqqt9/Q6gUxEJFTwyYHmRcATvEytv4sGLBXS4hYAol53GFBlDtWW X-Gm-Gg: ASbGncv6SxeH6q2H91yQCd5GfcHJtbktSvk6boCkhTHEQa//rINFCS9/TgXiA8YK2WU ztmA9ywY4dYJULRRPcpERiFJqefn0bhnr4DqPxy8wK9nKpb19V3wP2mxXFZhiVrrN8jGw4QqEmR 04NyfIikVDFhOqElgb0Fx0Ofxvb4Y+HOCO5zNkmHbLRYXpSM2EdaXnDPCm3yaMN7efk3z/u+jjG 5kFX2kFHYSRBjd1W/yy7gYNVg6xDwD11tQX/5sYzAXf8w1lYIaj3bBYi3Nz/pT4vHSCk91o2z5P /JxYjH6hNi6JZXyC4c9Mc1du4SSSYitKFVByHCFsQGhooOvsFXzoRT3DlpHygZH8C2FZ4qW7Gtn A4OrMnBTobqtPQllMCKrkFAc= X-Google-Smtp-Source: AGHT+IErgFYAXTPN+AzvrWatg1PvoZzWwKvf6LNCiI5p7gd1tVzCTDhVr+UkJW8OkXhswsTeNtW9YA== X-Received: by 2002:a05:600c:3ca0:b0:439:930a:58a6 with SMTP id 5b1f17b1804b1-43d438428a9mr992545e9.8.1742339336494; Tue, 18 Mar 2025 16:08:56 -0700 (PDT) Received: from 0e1b0684397b.v.cablecom.net (84-72-156-211.dclient.hispeed.ch. [84.72.156.211]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-43d440ed793sm1113455e9.39.2025.03.18.16.08.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 18 Mar 2025 16:08:55 -0700 (PDT) From: Lothar Rubusch To: lars@metafoo.de, Michael.Hennerich@analog.com, jic23@kernel.org Cc: linux-iio@vger.kernel.org, linux-kernel@vger.kernel.org, eraretuya@gmail.com, l.rubusch@gmail.com Subject: [PATCH v5 02/11] iio: accel: adxl345: add single tap feature Date: Tue, 18 Mar 2025 23:08:34 +0000 Message-Id: <20250318230843.76068-3-l.rubusch@gmail.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250318230843.76068-1-l.rubusch@gmail.com> References: <20250318230843.76068-1-l.rubusch@gmail.com> Precedence: bulk X-Mailing-List: linux-iio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Add the single tap feature with a threshold in 62.5mg/LSB points and a scaled duration in us. Keep singletap threshold in regmap cache but the scaled value of duration in us as member variable. Both use IIO channels for individual enable of the x/y/z axis. Initializes threshold and duration with reasonable content. When an interrupt is caught it will be pushed to the according IIO channel. Signed-off-by: Lothar Rubusch --- drivers/iio/accel/adxl345_core.c | 365 ++++++++++++++++++++++++++++++- 1 file changed, 362 insertions(+), 3 deletions(-) diff --git a/drivers/iio/accel/adxl345_core.c b/drivers/iio/accel/adxl345_core.c index a98fb7fc748e..86104840f2cc 100644 --- a/drivers/iio/accel/adxl345_core.c +++ b/drivers/iio/accel/adxl345_core.c @@ -8,6 +8,7 @@ */ #include +#include #include #include #include @@ -17,6 +18,7 @@ #include #include #include +#include #include #include "adxl345.h" @@ -31,6 +33,29 @@ #define ADXL345_INT1 0 #define ADXL345_INT2 1 +#define ADXL345_REG_TAP_AXIS_MSK GENMASK(2, 0) + +#define ADXL345_TAP_Z_EN BIT(0) +#define ADXL345_TAP_Y_EN BIT(1) +#define ADXL345_TAP_X_EN BIT(2) + +/* single/double tap */ +enum adxl345_tap_type { + ADXL345_SINGLE_TAP, +}; + +static const unsigned int adxl345_tap_int_reg[] = { + [ADXL345_SINGLE_TAP] = ADXL345_INT_SINGLE_TAP, +}; + +enum adxl345_tap_time_type { + ADXL345_TAP_TIME_DUR, +}; + +static const unsigned int adxl345_tap_time_reg[] = { + [ADXL345_TAP_TIME_DUR] = ADXL345_REG_DUR, +}; + struct adxl345_state { const struct adxl345_chip_info *info; struct regmap *regmap; @@ -38,9 +63,23 @@ struct adxl345_state { int irq; u8 watermark; u8 fifo_mode; + + u32 tap_duration_us; + __le16 fifo_buf[ADXL345_DIRS * ADXL345_FIFO_SIZE + 1] __aligned(IIO_DMA_MINALIGN); }; +static struct iio_event_spec adxl345_events[] = { + { + /* single tap */ + .type = IIO_EV_TYPE_GESTURE, + .dir = IIO_EV_DIR_SINGLETAP, + .mask_separate = BIT(IIO_EV_INFO_ENABLE), + .mask_shared_by_type = BIT(IIO_EV_INFO_VALUE) | + BIT(IIO_EV_INFO_TIMEOUT), + }, +}; + #define ADXL345_CHANNEL(index, reg, axis) { \ .type = IIO_ACCEL, \ .modified = 1, \ @@ -57,6 +96,8 @@ struct adxl345_state { .storagebits = 16, \ .endianness = IIO_LE, \ }, \ + .event_spec = adxl345_events, \ + .num_event_specs = ARRAY_SIZE(adxl345_events), \ } enum adxl345_chans { @@ -113,6 +154,150 @@ static int adxl345_set_measure_en(struct adxl345_state *st, bool en) return regmap_write(st->regmap, ADXL345_REG_POWER_CTL, val); } +/* tap */ + +static int _adxl345_set_tap_int(struct adxl345_state *st, + enum adxl345_tap_type type, bool state) +{ + unsigned int int_map = 0x00; + unsigned int tap_threshold; + bool axis_valid; + bool singletap_args_valid = false; + bool en = false; + u32 axis_ctrl; + int ret; + + ret = regmap_read(st->regmap, ADXL345_REG_TAP_AXIS, &axis_ctrl); + if (ret) + return ret; + + axis_valid = FIELD_GET(ADXL345_REG_TAP_AXIS_MSK, axis_ctrl) > 0; + + ret = regmap_read(st->regmap, ADXL345_REG_THRESH_TAP, &tap_threshold); + if (ret) + return ret; + + /* + * Note: A value of 0 for threshold and/or dur may result in undesirable + * behavior if single tap/double tap interrupts are enabled. + */ + singletap_args_valid = tap_threshold > 0 && st->tap_duration_us > 0; + + if (type == ADXL345_SINGLE_TAP) + en = axis_valid && singletap_args_valid; + + if (state && en) + int_map |= adxl345_tap_int_reg[type]; + + return regmap_update_bits(st->regmap, ADXL345_REG_INT_ENABLE, + adxl345_tap_int_reg[type], int_map); +} + +static int adxl345_is_tap_en(struct adxl345_state *st, + enum iio_modifier axis, + enum adxl345_tap_type type, bool *en) +{ + unsigned int regval; + bool axis_en; + u32 axis_ctrl; + int ret; + + ret = regmap_read(st->regmap, ADXL345_REG_TAP_AXIS, &axis_ctrl); + if (ret) + return ret; + + switch (axis) { + case IIO_MOD_X: + axis_en = FIELD_GET(ADXL345_TAP_X_EN, axis_ctrl); + break; + case IIO_MOD_Y: + axis_en = FIELD_GET(ADXL345_TAP_Y_EN, axis_ctrl); + break; + case IIO_MOD_Z: + axis_en = FIELD_GET(ADXL345_TAP_Z_EN, axis_ctrl); + break; + default: + return -EINVAL; + } + + ret = regmap_read(st->regmap, ADXL345_REG_INT_ENABLE, ®val); + if (ret) + return ret; + + *en = (adxl345_tap_int_reg[type] & regval) > 0; + + return 0; +} + +static int adxl345_set_singletap_en(struct adxl345_state *st, + enum iio_modifier axis, bool en) +{ + int ret; + u32 axis_ctrl; + + switch (axis) { + case IIO_MOD_X: + axis_ctrl = ADXL345_TAP_X_EN; + break; + case IIO_MOD_Y: + axis_ctrl = ADXL345_TAP_Y_EN; + break; + case IIO_MOD_Z: + axis_ctrl = ADXL345_TAP_Z_EN; + break; + default: + return -EINVAL; + } + + if (en) + ret = regmap_set_bits(st->regmap, ADXL345_REG_TAP_AXIS, + axis_ctrl); + else + ret = regmap_clear_bits(st->regmap, ADXL345_REG_TAP_AXIS, + axis_ctrl); + if (ret) + return ret; + + return _adxl345_set_tap_int(st, ADXL345_SINGLE_TAP, en); +} + +static int _adxl345_set_tap_time(struct adxl345_state *st, + enum adxl345_tap_time_type type, u32 val_us) +{ + unsigned int regval; + + switch (type) { + case ADXL345_TAP_TIME_DUR: + st->tap_duration_us = val_us; + break; + } + + /* + * The scale factor is 1250us / LSB for tap_window_us and tap_latent_us. + * For tap_duration_us the scale factor is 625us / LSB. + */ + if (type == ADXL345_TAP_TIME_DUR) + regval = DIV_ROUND_CLOSEST(val_us, 625); + else + regval = DIV_ROUND_CLOSEST(val_us, 1250); + + return regmap_write(st->regmap, adxl345_tap_time_reg[type], regval); +} + +static int adxl345_set_tap_duration(struct adxl345_state *st, u32 val_int, + u32 val_fract_us) +{ + /* + * Max value is 255 * 625 us = 0.159375 seconds + * + * Note: the scaling is similar to the scaling in the ADXL380 + */ + if (val_int || val_fract_us > 159375) + return -EINVAL; + + return _adxl345_set_tap_time(st, ADXL345_TAP_TIME_DUR, val_fract_us); +} + static int adxl345_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask) @@ -198,6 +383,131 @@ static int adxl345_write_raw(struct iio_dev *indio_dev, return -EINVAL; } +static int adxl345_read_event_config(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir) +{ + struct adxl345_state *st = iio_priv(indio_dev); + bool int_en; + int ret; + + switch (type) { + case IIO_EV_TYPE_GESTURE: + switch (dir) { + case IIO_EV_DIR_SINGLETAP: + ret = adxl345_is_tap_en(st, chan->channel2, + ADXL345_SINGLE_TAP, &int_en); + if (ret) + return ret; + return int_en; + default: + return -EINVAL; + } + default: + return -EINVAL; + } +} + +static int adxl345_write_event_config(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + int state) +{ + struct adxl345_state *st = iio_priv(indio_dev); + + switch (type) { + case IIO_EV_TYPE_GESTURE: + switch (dir) { + case IIO_EV_DIR_SINGLETAP: + return adxl345_set_singletap_en(st, chan->channel2, state); + 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, + enum iio_event_direction dir, + enum iio_event_info info, + int *val, int *val2) +{ + struct adxl345_state *st = iio_priv(indio_dev); + unsigned int tap_threshold; + int ret; + + switch (type) { + case IIO_EV_TYPE_GESTURE: + switch (info) { + case IIO_EV_INFO_VALUE: + /* + * The scale factor would be 62.5mg/LSB (i.e. 0xFF = 16g) but + * not applied here. In context of this general purpose sensor, + * what imports is rather signal intensity than the absolute + * measured g value. + */ + ret = regmap_read(st->regmap, ADXL345_REG_THRESH_TAP, + &tap_threshold); + if (ret) + return ret; + *val = sign_extend32(tap_threshold, 7); + return IIO_VAL_INT; + case IIO_EV_INFO_TIMEOUT: + *val = st->tap_duration_us; + *val2 = 1000000; + return IIO_VAL_FRACTIONAL; + default: + return -EINVAL; + } + default: + return -EINVAL; + } +} + +static int adxl345_write_event_value(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + enum iio_event_info info, + int val, int val2) +{ + struct adxl345_state *st = iio_priv(indio_dev); + int ret; + + ret = adxl345_set_measure_en(st, false); + if (ret) + return ret; + + switch (type) { + case IIO_EV_TYPE_GESTURE: + switch (info) { + case IIO_EV_INFO_VALUE: + ret = regmap_write(st->regmap, ADXL345_REG_THRESH_TAP, + min(val, 0xFF)); + if (ret) + return ret; + break; + case IIO_EV_INFO_TIMEOUT: + ret = adxl345_set_tap_duration(st, val, val2); + if (ret) + return ret; + break; + default: + return -EINVAL; + } + break; + default: + return -EINVAL; + } + + return adxl345_set_measure_en(st, true); +} + static int adxl345_reg_access(struct iio_dev *indio_dev, unsigned int reg, unsigned int writeval, unsigned int *readval) { @@ -416,10 +726,23 @@ static int adxl345_fifo_push(struct iio_dev *indio_dev, return 0; } -static int adxl345_push_event(struct iio_dev *indio_dev, int int_stat) +static int adxl345_push_event(struct iio_dev *indio_dev, int int_stat, + enum iio_modifier tap_dir) { + s64 ts = iio_get_time_ns(indio_dev); struct adxl345_state *st = iio_priv(indio_dev); int samples; + int ret = -ENOENT; + + if (FIELD_GET(ADXL345_INT_SINGLE_TAP, int_stat)) { + ret = iio_push_event(indio_dev, + IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, tap_dir, + IIO_EV_TYPE_GESTURE, + IIO_EV_DIR_SINGLETAP), + ts); + if (ret) + return ret; + } if (FIELD_GET(ADXL345_INT_WATERMARK, int_stat)) { samples = adxl345_get_samples(st); @@ -428,9 +751,11 @@ static int adxl345_push_event(struct iio_dev *indio_dev, int int_stat) if (adxl345_fifo_push(indio_dev, samples) < 0) return -EINVAL; + + return 0; } - return 0; + return ret; } /** @@ -444,12 +769,33 @@ static irqreturn_t adxl345_irq_handler(int irq, void *p) { struct iio_dev *indio_dev = p; struct adxl345_state *st = iio_priv(indio_dev); + unsigned int regval; + enum iio_modifier tap_dir = IIO_NO_MOD; + u32 axis_ctrl; int int_stat; + int ret; + + ret = regmap_read(st->regmap, ADXL345_REG_TAP_AXIS, &axis_ctrl); + if (ret) + return IRQ_NONE; + + if (FIELD_GET(ADXL345_REG_TAP_AXIS_MSK, axis_ctrl)) { + ret = regmap_read(st->regmap, ADXL345_REG_ACT_TAP_STATUS, ®val); + if (ret) + return IRQ_NONE; + + if (FIELD_GET(ADXL345_TAP_Z_EN, regval)) + tap_dir = IIO_MOD_Z; + else if (FIELD_GET(ADXL345_TAP_Y_EN, regval)) + tap_dir = IIO_MOD_Y; + else if (FIELD_GET(ADXL345_TAP_X_EN, regval)) + tap_dir = IIO_MOD_X; + } if (regmap_read(st->regmap, ADXL345_REG_INT_SOURCE, &int_stat)) return IRQ_NONE; - if (adxl345_push_event(indio_dev, int_stat)) + if (adxl345_push_event(indio_dev, int_stat, tap_dir)) goto err; if (FIELD_GET(ADXL345_INT_OVERRUN, int_stat)) @@ -468,6 +814,10 @@ static const struct iio_info adxl345_info = { .read_raw = adxl345_read_raw, .write_raw = adxl345_write_raw, .write_raw_get_fmt = adxl345_write_raw_get_fmt, + .read_event_config = adxl345_read_event_config, + .write_event_config = adxl345_write_event_config, + .read_event_value = adxl345_read_event_value, + .write_event_value = adxl345_write_event_value, .debugfs_reg_access = &adxl345_reg_access, .hwfifo_set_watermark = adxl345_set_watermark, }; @@ -501,6 +851,7 @@ int adxl345_core_probe(struct device *dev, struct regmap *regmap, ADXL345_DATA_FORMAT_JUSTIFY | ADXL345_DATA_FORMAT_FULL_RES | ADXL345_DATA_FORMAT_SELF_TEST); + unsigned int tap_threshold; int ret; indio_dev = devm_iio_device_alloc(dev, sizeof(*st)); @@ -514,6 +865,10 @@ int adxl345_core_probe(struct device *dev, struct regmap *regmap, return -ENODEV; st->fifo_delay = fifo_delay_default; + /* Init with reasonable values */ + tap_threshold = 48; /* 48 [0x30] -> ~3g */ + st->tap_duration_us = 16; /* 16 [0x10] -> .010 */ + indio_dev->name = st->info->name; indio_dev->info = &adxl345_info; indio_dev->modes = INDIO_DIRECT_MODE; @@ -586,6 +941,10 @@ int adxl345_core_probe(struct device *dev, struct regmap *regmap, if (ret) return ret; + ret = regmap_write(st->regmap, ADXL345_REG_THRESH_TAP, tap_threshold); + if (ret) + return ret; + /* FIFO_STREAM mode is going to be activated later */ ret = devm_iio_kfifo_buffer_setup(dev, indio_dev, &adxl345_buffer_ops); if (ret) From patchwork Tue Mar 18 23:08:35 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lothar Rubusch X-Patchwork-Id: 14021716 Received: from mail-wm1-f48.google.com (mail-wm1-f48.google.com [209.85.128.48]) (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 8B3D02135A9; Tue, 18 Mar 2025 23:08:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.48 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742339341; cv=none; b=ju20rIAlGG0eoknnBDAO1X8QIMnGpO7FPiNHVA7EPazckGzsj1m/fglnVMyviWCYLoD1dfy35rya6r558F12QLEGUA+JZWlNnigsGabRTyJe9IYAlgw6D50fDmH5YX83+yZj6TKT2PIh4mmTF91hf9lnhpgVWVkgoLAbc/nzTiU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742339341; c=relaxed/simple; bh=PnA3gkAKR9j1sQPf2K2flhREM56meu3VB7HAqRauyC4=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=X95grRwVac2lpYx6l9bNsy9O0FtHsYFINR7KvIdjD4lgYbK2VjHvlgmHLB6XlUIpy1Bb0axkBFSNtyWrmYHRRRt9AgvvlDeW7rci8YMcJwUALGruX1kNs5pzyohecfqjZtxMueR8iiylshZWY0GvUTcINJk2jTfMv7P5va5QA2k= 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=MDukmi+o; arc=none smtp.client-ip=209.85.128.48 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="MDukmi+o" Received: by mail-wm1-f48.google.com with SMTP id 5b1f17b1804b1-43938828d02so6397105e9.1; Tue, 18 Mar 2025 16:08:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1742339338; x=1742944138; 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=dB0EYpnHKI9P7vCaj/PqV9XKwE6uJs4DCnLjT7T6Du4=; b=MDukmi+oTd75mL5ESjASmBs+fGZcIKTY5FS8lp536fG+NcCv4Y/aR+AFRkiQYFMDr/ QE2rsg7r733GVvFc4fBd3sGFxInKXu/kezRAuwemsKH6M8fPhKlmLgfyrLGdiX6aLm3U HMXfK0XlxrO0e7t5wVcXda6LlaqLKWuaeSXI6DKHSl0gOSlH9E4C+JXHC0VrLrDnKOKW 2knIT4V0MwRFGVYHoYs+PCpnIRy4R14LTa6RER6cBdRMcI8jde5JIGdvZuUbCI+QZ1k+ V4quDdu/tRZGpvOvEPW08MCgH1btX0CniWhu4dgP9Mhxo/32idnwSbRLyRrvol1QXE8M gyDw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1742339338; x=1742944138; 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=dB0EYpnHKI9P7vCaj/PqV9XKwE6uJs4DCnLjT7T6Du4=; b=lC3jmX3hghSJzHUVNoERHjzCKDVa63WMj0qna56rh6qKk+8fEI/yJ9uNM67s1U9KBt 9nTjR3b/HcMegDFeMYDDpDIbyRJ+8vdRgV9Ds9iK509PSRqVwIktYCPHA21TPQWqaq42 ZLNYFrsyPkoSfjQMubZTsklI09Wqb2HFBCNU7qFeOTm8w+2Aem9n6xjNteKWjjy6YZto BojT8as+9r07XjvjXt2dZRSRSFuz/A7WxCUUXwg7o9NiboyV2+ytGrImExeFfU5AMKCK ew+gqFCSwj3ewM+sE8sFTVUpyMKDKajBKBQvKMccgHwW4g9VrN+ss+imgmZ9Vcz1/zF3 imhw== X-Forwarded-Encrypted: i=1; AJvYcCWqLTB10C+4z5NtNG5vfz47z1sJvjKE64G2H0jFReVqvpzqcgIQgBs56cUmeKmiAx1jS6VDLmOk7jtBI4Q=@vger.kernel.org X-Gm-Message-State: AOJu0YzMp08jx8+n+sbfggaiN3yetIl26l63UXWha/ugDnbOG1r8q+u5 Dg0yTVaz+36hWIpBT62mZhhQ8NtAlS88fhwLk3XFlHPXURm4FX3A X-Gm-Gg: ASbGncspW9Dq9u0sC7b4Fq1SV/hlAX+jQJEkj167Fcxli1SB/JeBQ9GYO4zqPezyk/7 T+5bvvnN4YoiGsdv1noSqkwW780ruP062+fcysckHDiVXa9YmnbktHnxc/q9rU7F1ZhUCGGAD4R Eg6WvyIAokbIgCeSWag9SALLtJSzZVbcODFe+urfmUFqaZZX98Qa903afh+svsL4ntbzKHLzMdY 2lpm/sdN62Dp1EKJaLqgQpu+8g45c7HoBcHM0yqJXRKRGo8yKwk0bzqzMSKScd+6a6rLQWq5uRw L+VrQzzWr9NwjF1xedrodbbwx8cBh/Wu2M5u3UbyA90NzWke6p65t0RlBoeq1YOnzvEghMWNppy rIs50N2vlEZx79IjQVJCHVeOo/s5LQCETtQ== X-Google-Smtp-Source: AGHT+IFfGATH3y/DPGOJdMbFGfXj9JGiUziISkXYBPrT/5awBuWT+CUjXg3fMaGoBIFCUBqq7hG3vg== X-Received: by 2002:a05:600c:1d0e:b0:43b:c938:1d0e with SMTP id 5b1f17b1804b1-43d43781b95mr1157865e9.2.1742339337644; Tue, 18 Mar 2025 16:08:57 -0700 (PDT) Received: from 0e1b0684397b.v.cablecom.net (84-72-156-211.dclient.hispeed.ch. [84.72.156.211]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-43d440ed793sm1113455e9.39.2025.03.18.16.08.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 18 Mar 2025 16:08:57 -0700 (PDT) From: Lothar Rubusch To: lars@metafoo.de, Michael.Hennerich@analog.com, jic23@kernel.org Cc: linux-iio@vger.kernel.org, linux-kernel@vger.kernel.org, eraretuya@gmail.com, l.rubusch@gmail.com Subject: [PATCH v5 03/11] iio: accel: adxl345: add double tap feature Date: Tue, 18 Mar 2025 23:08:35 +0000 Message-Id: <20250318230843.76068-4-l.rubusch@gmail.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250318230843.76068-1-l.rubusch@gmail.com> References: <20250318230843.76068-1-l.rubusch@gmail.com> Precedence: bulk X-Mailing-List: linux-iio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Add the double tap feature of the sensor. The interrupt handler needs to catch and forward the event to the IIO channel. The single tap implementation now is extended to deal with double tap as well. Doubletap introduces window and latency times, both in us. Since both times are scaled, the 8-bit register value is stored in hardware, where the scaled value in [us] is stored as member variable. Signed-off-by: Lothar Rubusch --- drivers/iio/accel/adxl345_core.c | 104 ++++++++++++++++++++++++++++++- 1 file changed, 103 insertions(+), 1 deletion(-) diff --git a/drivers/iio/accel/adxl345_core.c b/drivers/iio/accel/adxl345_core.c index 86104840f2cc..9dee819d5252 100644 --- a/drivers/iio/accel/adxl345_core.c +++ b/drivers/iio/accel/adxl345_core.c @@ -42,17 +42,23 @@ /* single/double tap */ enum adxl345_tap_type { ADXL345_SINGLE_TAP, + ADXL345_DOUBLE_TAP, }; static const unsigned int adxl345_tap_int_reg[] = { [ADXL345_SINGLE_TAP] = ADXL345_INT_SINGLE_TAP, + [ADXL345_DOUBLE_TAP] = ADXL345_INT_DOUBLE_TAP, }; enum adxl345_tap_time_type { + ADXL345_TAP_TIME_LATENT, + ADXL345_TAP_TIME_WINDOW, ADXL345_TAP_TIME_DUR, }; static const unsigned int adxl345_tap_time_reg[] = { + [ADXL345_TAP_TIME_LATENT] = ADXL345_REG_LATENT, + [ADXL345_TAP_TIME_WINDOW] = ADXL345_REG_WINDOW, [ADXL345_TAP_TIME_DUR] = ADXL345_REG_DUR, }; @@ -65,6 +71,8 @@ struct adxl345_state { u8 fifo_mode; u32 tap_duration_us; + u32 tap_latent_us; + u32 tap_window_us; __le16 fifo_buf[ADXL345_DIRS * ADXL345_FIFO_SIZE + 1] __aligned(IIO_DMA_MINALIGN); }; @@ -78,6 +86,14 @@ static struct iio_event_spec adxl345_events[] = { .mask_shared_by_type = BIT(IIO_EV_INFO_VALUE) | BIT(IIO_EV_INFO_TIMEOUT), }, + { + /* double tap */ + .type = IIO_EV_TYPE_GESTURE, + .dir = IIO_EV_DIR_DOUBLETAP, + .mask_shared_by_type = BIT(IIO_EV_INFO_ENABLE) | + BIT(IIO_EV_INFO_RESET_TIMEOUT) | + BIT(IIO_EV_INFO_TAP2_MIN_DELAY), + }, }; #define ADXL345_CHANNEL(index, reg, axis) { \ @@ -163,6 +179,7 @@ static int _adxl345_set_tap_int(struct adxl345_state *st, unsigned int tap_threshold; bool axis_valid; bool singletap_args_valid = false; + bool doubletap_args_valid = false; bool en = false; u32 axis_ctrl; int ret; @@ -183,8 +200,16 @@ static int _adxl345_set_tap_int(struct adxl345_state *st, */ singletap_args_valid = tap_threshold > 0 && st->tap_duration_us > 0; - if (type == ADXL345_SINGLE_TAP) + if (type == ADXL345_SINGLE_TAP) { en = axis_valid && singletap_args_valid; + } else { + /* doubletap: Window must be equal or greater than latent! */ + doubletap_args_valid = st->tap_latent_us > 0 && + st->tap_window_us > 0 && + st->tap_window_us >= st->tap_latent_us; + + en = axis_valid && singletap_args_valid && doubletap_args_valid; + } if (state && en) int_map |= adxl345_tap_int_reg[type]; @@ -261,12 +286,23 @@ static int adxl345_set_singletap_en(struct adxl345_state *st, return _adxl345_set_tap_int(st, ADXL345_SINGLE_TAP, en); } +static int adxl345_set_doubletap_en(struct adxl345_state *st, bool en) +{ + return _adxl345_set_tap_int(st, ADXL345_DOUBLE_TAP, en); +} + static int _adxl345_set_tap_time(struct adxl345_state *st, enum adxl345_tap_time_type type, u32 val_us) { unsigned int regval; switch (type) { + case ADXL345_TAP_TIME_WINDOW: + st->tap_window_us = val_us; + break; + case ADXL345_TAP_TIME_LATENT: + st->tap_latent_us = val_us; + break; case ADXL345_TAP_TIME_DUR: st->tap_duration_us = val_us; break; @@ -298,6 +334,34 @@ static int adxl345_set_tap_duration(struct adxl345_state *st, u32 val_int, return _adxl345_set_tap_time(st, ADXL345_TAP_TIME_DUR, val_fract_us); } +static int adxl345_set_tap_window(struct adxl345_state *st, u32 val_int, + u32 val_fract_us) +{ + /* + * Max value is 255 * 1250 us = 0.318750 seconds + * + * Note: the scaling is similar to the scaling in the ADXL380 + */ + if (val_int || val_fract_us > 318750) + return -EINVAL; + + return _adxl345_set_tap_time(st, ADXL345_TAP_TIME_WINDOW, val_fract_us); +} + +static int adxl345_set_tap_latent(struct adxl345_state *st, u32 val_int, + u32 val_fract_us) +{ + /* + * Max value is 255 * 1250 us = 0.318750 seconds + * + * Note: the scaling is similar to the scaling in the ADXL380 + */ + if (val_int || val_fract_us > 318750) + return -EINVAL; + + return _adxl345_set_tap_time(st, ADXL345_TAP_TIME_LATENT, val_fract_us); +} + static int adxl345_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask) @@ -401,6 +465,12 @@ static int adxl345_read_event_config(struct iio_dev *indio_dev, if (ret) return ret; return int_en; + case IIO_EV_DIR_DOUBLETAP: + ret = adxl345_is_tap_en(st, chan->channel2, + ADXL345_DOUBLE_TAP, &int_en); + if (ret) + return ret; + return int_en; default: return -EINVAL; } @@ -422,6 +492,8 @@ static int adxl345_write_event_config(struct iio_dev *indio_dev, switch (dir) { case IIO_EV_DIR_SINGLETAP: return adxl345_set_singletap_en(st, chan->channel2, state); + case IIO_EV_DIR_DOUBLETAP: + return adxl345_set_doubletap_en(st, state); default: return -EINVAL; } @@ -461,6 +533,14 @@ static int adxl345_read_event_value(struct iio_dev *indio_dev, *val = st->tap_duration_us; *val2 = 1000000; return IIO_VAL_FRACTIONAL; + case IIO_EV_INFO_RESET_TIMEOUT: + *val = st->tap_window_us; + *val2 = 1000000; + return IIO_VAL_FRACTIONAL; + case IIO_EV_INFO_TAP2_MIN_DELAY: + *val = st->tap_latent_us; + *val2 = 1000000; + return IIO_VAL_FRACTIONAL; default: return -EINVAL; } @@ -497,6 +577,16 @@ static int adxl345_write_event_value(struct iio_dev *indio_dev, if (ret) return ret; break; + case IIO_EV_INFO_RESET_TIMEOUT: + ret = adxl345_set_tap_window(st, val, val2); + if (ret) + return ret; + break; + case IIO_EV_INFO_TAP2_MIN_DELAY: + ret = adxl345_set_tap_latent(st, val, val2); + if (ret) + return ret; + break; default: return -EINVAL; } @@ -744,6 +834,16 @@ static int adxl345_push_event(struct iio_dev *indio_dev, int int_stat, return ret; } + if (FIELD_GET(ADXL345_INT_DOUBLE_TAP, int_stat)) { + ret = iio_push_event(indio_dev, + IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, tap_dir, + IIO_EV_TYPE_GESTURE, + IIO_EV_DIR_DOUBLETAP), + ts); + if (ret) + return ret; + } + if (FIELD_GET(ADXL345_INT_WATERMARK, int_stat)) { samples = adxl345_get_samples(st); if (samples < 0) @@ -868,6 +968,8 @@ int adxl345_core_probe(struct device *dev, struct regmap *regmap, /* Init with reasonable values */ tap_threshold = 48; /* 48 [0x30] -> ~3g */ st->tap_duration_us = 16; /* 16 [0x10] -> .010 */ + st->tap_window_us = 64; /* 64 [0x40] -> .080 */ + st->tap_latent_us = 16; /* 16 [0x10] -> .020 */ indio_dev->name = st->info->name; indio_dev->info = &adxl345_info; From patchwork Tue Mar 18 23:08:36 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lothar Rubusch X-Patchwork-Id: 14021717 Received: from mail-wm1-f53.google.com (mail-wm1-f53.google.com [209.85.128.53]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 866152139B0; Tue, 18 Mar 2025 23:09:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.53 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742339342; cv=none; b=N3rXgXLsCL+3omHVDHIaoO/5ILDYTlXC0FH+iZusQUbnhrPNl35fJZ8Hf53oyOvNzxAzefRoU9XZVrh4kALvsxHTpthqmsvwYj0ahbnSOYsdEh7iQfOOMNFfMjDXXtU7YKP5mNMSBOcnOXf8yltCcQpf/PUQar3Er4e0NktHWlA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742339342; c=relaxed/simple; bh=kTuk4oS1Z5MqPEpTNJY/RFfU8sOm/9Vfhefz+HHDWy4=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=ZoDOwgoNxaexq+uHX3Rz/ilx4LxfnofIXBTY0JcqwghZJHMXVbvIgdkmNkZXapBygZN8wYt3Z2+qLhl4dC/nRgbkJ4VsROYgHk945qkh3E5QtH13C3f5W/btIwEwrouqR2+X1taKXWMVLxxKgItq/u5oAg0uq6ihjcJSJugvnAw= 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=UM8s/p6D; arc=none smtp.client-ip=209.85.128.53 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="UM8s/p6D" Received: by mail-wm1-f53.google.com with SMTP id 5b1f17b1804b1-43d0953d3e1so3861255e9.2; Tue, 18 Mar 2025 16:09:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1742339339; x=1742944139; 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=mK9Gt9waVp5YavrmSeXRxGHtVUUg9Z23BLqhVi00yoA=; b=UM8s/p6D2it/OlpRuWXhECh6zOMRgvW5WYAX+GORN8uTbvkV/HkAGQxV2+QS6K3cfQ MKF7qhm3ErG8DUVxv2VmHoPBd90RINnxiOCppKt/Bt76kiISwVhe4vBh/a5huKOe4QkO Ec/OggJ8io4hfhXc9AgPqECKJX30ZR1iS3w9CUUUVPJss+9JfVT1igHr9hIvQUkF0d4E riWy9HweFU8OpEYop141qI8G3yWuIzAc8fq2/5SBP16jrjJ6CxwB33sR3ZyGEKy39o6m 5y6SLLLbfeg0wpJCR+OeiuVHJojp47aTDANvg3k+L6mzJG6OGdZXYX8tdzvYDHx0FUJp dPTQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1742339339; x=1742944139; 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=mK9Gt9waVp5YavrmSeXRxGHtVUUg9Z23BLqhVi00yoA=; b=kUG2PvrfRcSF0CMO9nxTj6IGVx8kHxr856WxQq7ykkiH9/xIL7uiLkZnv1ymgToPni B5UXXec4jmVWDaDzRQa//Hc3lc9OtzaYu1zlbnj0210QBG5JBsnyfOy1Fu4hyjlRSQ/C JUIK0jj2chbK9QfBUkp6s8xwsCUA7TK1ntT2avfolUtFXTTJRLgAwv3ItkoFWgFkRUut m53NunuM/UTVX6cQCuRnj4yj6Dr3ZU1pBGOmFUQwnUU2bOOI3/4Om00cJ3bairsmGWHI XHu+RdnwW3EnWNsBmQtew1bbVfAvuvykpSsL7FYlZJIgG2PHcKVS5tGzCa+lDmnGNBx9 yXgQ== X-Forwarded-Encrypted: i=1; AJvYcCXLbDL+oQ74OcXk/+Nhs+KodrlFmIAPz6F7vGZcMW5ywE44UTmj0Xw0mp8ENG0r8Vd+IF1bG3FZgvKqUDY=@vger.kernel.org X-Gm-Message-State: AOJu0YzrOSl8cqK9qDOOWFIXvHXIUhVFkrTz3oFa67KjYdEtNmQt8/ST DmQ6i4O8tFlxguh3Yab+82DKzBJ8h2TBSQu1upSrhDTWMuzdVtdS X-Gm-Gg: ASbGncuUdy8fDftrgD/unidYV5NYWEVlFjRxDm96PmSSiUMdLGtWFB2cVmQw2stDgh/ 6FOyhhQXRhNIlv0vAzqAmPCKI/0RbUbCl+3uDEGzuutcHPtRLsKZSHV4Yqo0qZu5XBh6nOEEDja 04ZfNgxPyrQ5/xF3LMv9J3L3ZhH53r0mtz6dXAl2jq7gD/EBmZXdPxMAou4taz2T6XSH1ZAUok8 z/xI6JSTxxtOZ+9mrokqyUINecoIg9JOG9C8DOS/bLZPX08hg/3YJzod5qsTTNU62hBljhQDwqD i+cBle42QYVtQkPrQedxkEGg6TynYsvAIjPngVX+LgwM3la4/mCC9W0Iw5AHdjzICL/rWzqK7zP BS74AHWY8ZmVyzMyBy1aSIG4= X-Google-Smtp-Source: AGHT+IHCsLWjI3h37CbyOLS5zu4xP3emYSD3vqaqnjAUpFHi/hya9/9aOGP9QmiJhvU6AjxJspey/Q== X-Received: by 2002:a05:600c:1d88:b0:43b:c844:a4ba with SMTP id 5b1f17b1804b1-43d4387586amr1043795e9.3.1742339338604; Tue, 18 Mar 2025 16:08:58 -0700 (PDT) Received: from 0e1b0684397b.v.cablecom.net (84-72-156-211.dclient.hispeed.ch. [84.72.156.211]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-43d440ed793sm1113455e9.39.2025.03.18.16.08.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 18 Mar 2025 16:08:58 -0700 (PDT) From: Lothar Rubusch To: lars@metafoo.de, Michael.Hennerich@analog.com, jic23@kernel.org Cc: linux-iio@vger.kernel.org, linux-kernel@vger.kernel.org, eraretuya@gmail.com, l.rubusch@gmail.com Subject: [PATCH v5 04/11] iio: accel: adxl345: set the tap suppress bit permanently Date: Tue, 18 Mar 2025 23:08:36 +0000 Message-Id: <20250318230843.76068-5-l.rubusch@gmail.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250318230843.76068-1-l.rubusch@gmail.com> References: <20250318230843.76068-1-l.rubusch@gmail.com> Precedence: bulk X-Mailing-List: linux-iio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Set the suppress bit feature to the double tap detection, whenever double tap is enabled. This impedes the suppress bit dangling in any state, and thus varying in sensitivity for double tap detection. Any tap event is defined by a rising signal edge above threshold, i.e. duration time starts counting; and the falling edge under threshold within duration time, i.e. then the tap event is issued. This means duration is used individually for each tap event. For double tap detection after a single tap, a latency time needs to be specified. Usually tap events, i.e. spikes above and returning below threshold will be ignored within latency. After latency, the window time starts counting for a second tap detection which has to happen within a duration time. If the suppress bit is not set, spikes within latency time are ignored. Setting the suppress bit will invalidate the double tap function. The sensor will thus be able to save the window time for double tap detection, and follow a more strict definition of what signal qualifies for a double tap. In a summary having the suppress bit set, fewer signal spikes will be considered as double taps. This is an optional add on to double tap, thus a separate patch. Signed-off-by: Lothar Rubusch --- drivers/iio/accel/adxl345_core.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/iio/accel/adxl345_core.c b/drivers/iio/accel/adxl345_core.c index 9dee819d5252..52daf46c4acd 100644 --- a/drivers/iio/accel/adxl345_core.c +++ b/drivers/iio/accel/adxl345_core.c @@ -34,6 +34,8 @@ #define ADXL345_INT2 1 #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_TAP_Z_EN BIT(0) #define ADXL345_TAP_Y_EN BIT(1) @@ -288,6 +290,18 @@ static int adxl345_set_singletap_en(struct adxl345_state *st, static int adxl345_set_doubletap_en(struct adxl345_state *st, bool en) { + int ret; + + /* + * Generally suppress detection of spikes during the latency period as + * double taps here, this is fully optional for double tap detection + */ + ret = regmap_update_bits(st->regmap, ADXL345_REG_TAP_AXIS, + ADXL345_REG_TAP_SUPPRESS_MSK, + en ? ADXL345_REG_TAP_SUPPRESS : 0x00); + if (ret) + return ret; + return _adxl345_set_tap_int(st, ADXL345_DOUBLE_TAP, en); } From patchwork Tue Mar 18 23:08:37 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lothar Rubusch X-Patchwork-Id: 14021718 Received: from mail-wr1-f52.google.com (mail-wr1-f52.google.com [209.85.221.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 CA858214217; Tue, 18 Mar 2025 23:09:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.52 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742339343; cv=none; b=fdSQ2NOka7QRkRN0PsDny5VQvVXSpskPQZWTQfnhsDunczUo77reS0qCd+E6x4/jsSFq9A/PNUqEPUOy0YAW4YxFFxbxVHS4Ll+0pth8VfKUM2939kAHMAGXUJg7RVbsBipI2itzMz/nqH+0BF+lvPMuF3t/01895k44qaLHCHc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742339343; c=relaxed/simple; bh=gIx7mxQLDoUZcS9OQy9xSQ7npBFbtDddjzOZeHfc8Rg=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=AjAfRxUpmnEjq5JSgI/N53RQuV0218b65bSKUjc1SXwJVw5sTxNkBZBSUr6UMwFjcRxX5QybnsDgSRLFj1bWXl7BJEbJenBZSFldxRBcI6B9ZkCiBjpbQqKLGyyc2f4MzzEjzLIEfEIrxOuyM+Y66IElXTRku3afLgyIgpfCUFo= 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=aTMh/dnX; arc=none smtp.client-ip=209.85.221.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="aTMh/dnX" Received: by mail-wr1-f52.google.com with SMTP id ffacd0b85a97d-39123d2eb7fso810084f8f.1; Tue, 18 Mar 2025 16:09:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1742339340; x=1742944140; 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=Af8+S+Iqm4Cd36iKsf8R3DH0P2+TW/TcPm1Vexd8UEA=; b=aTMh/dnXVeWObvd0Bj+asjEL0D0QtQjJ1S8+qCV6rZh/6qoziL1+A+q2hJTcuNs9UT iJRD03cFRtYFNG+JEvIJV7nOWZoNup+uh/g/wN0gvOHKcj6Ja1rSCg6H9LdlJzg9f0tA CHFYVbvLfbh00qnOsDIxCP9TIAM30/vq2r9seF4rjXWeh5Dwt64mBJ7G0xU5YMC0eCot EqhOtfEpzpN7rH6oEW2+P1ylbnNp2CI5eu3LtpkQj9WtQscZIXjbrG7CuTc9Y3yLLkko QBPAnpzmjtzkgWcrcwnr/XVv9+u375m4RHHZSTF12VrLlVx+17w7Pe/ZQ2VayWSbIL2m +ZLg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1742339340; x=1742944140; 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=Af8+S+Iqm4Cd36iKsf8R3DH0P2+TW/TcPm1Vexd8UEA=; b=DwGgUpV6pdBa9YANX+0sybxzM/H5mkcReKh2j2/qCHug6oUHsDVPEfSMHWHa7XQz+h Div/sl77BovA8LAqA5zp19qXr1uhrHFIOtnJyZdhVAMp+FZVscoJAvbouXQMYsmnrr9N ohxYD6k7/m+hS/P1/24f5xd/BJe3rJ1X8HwpOn72oS5Ylnie1JxDbf4/ZXM3vGHC6jtc A2qzHNRG0mhcA6IcCPWfGzqUhB398FDJUcevrLlqkgX9/1cawkQNs6IrRV/TowU8c5kZ z4qRteGKwDTbPGTt7YH2NS5aBpHrXtjCkUXVL61p5AJzmu+zihmKKEgG1bdDjGpB2YOx +RUA== X-Forwarded-Encrypted: i=1; AJvYcCV1atKGYbmob+uR/PCaTF917lIWwcCblwOYsZslGus7pZPNk36gHC5ryT6C+E0/xiClfjeDhymzsKXeoVw=@vger.kernel.org X-Gm-Message-State: AOJu0Yy+0JlDMDyv4kH0PKhWP8+mK7loLlXVS5H18je2XouT0znqX1bX WivysUYe2N9QSN8UEJFGwQtXKTsn0IEzGQYJ9v8SZK9TKJfLUPt7 X-Gm-Gg: ASbGncvhxY+UrRT+L5rFPUpaXm/FqzA0N6a6feidUc5I+/8a1KJ1ef4faHC40Gsp8N0 sMUft22WYh7JExig0y9a2UB9AVlnKPkPYtEKTD6fD7aB1AgTF2TZwqAnO2nIpsPo6wIG0j2xJcP 2o6fpLzsyfEtndGhYSU3b6iThlPTag8sm4m3Crhdx6OTtBBMF6uwk2RxELHlsv2hC9votZepLLw nfwuLu4nJYHMJWJUi9RqVIExBHBFsdM6FTPyl4E/VuCuh7kJmXkg/HVWIiRJitTp6ERe8hq43Q4 RiBQZM8dTvvfsYyCvd8rTn+3ZQeOQ5wrKkfHM9uSllRbJv8NL77aTdk07KbIy196Z4mWxyJh9bd fQRTAe9DPOk8cR7Owku347NI= X-Google-Smtp-Source: AGHT+IEYb6yR9aCl/Sm1DJOhI88C2Vh5s5yKxEaGtUh0r3ndO3O3zfNq8wzgH6S0YUiG6Nr8kd0+YA== X-Received: by 2002:a5d:5985:0:b0:38f:20b5:2c80 with SMTP id ffacd0b85a97d-399739f08camr153905f8f.6.1742339339842; Tue, 18 Mar 2025 16:08:59 -0700 (PDT) Received: from 0e1b0684397b.v.cablecom.net (84-72-156-211.dclient.hispeed.ch. [84.72.156.211]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-43d440ed793sm1113455e9.39.2025.03.18.16.08.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 18 Mar 2025 16:08:59 -0700 (PDT) From: Lothar Rubusch To: lars@metafoo.de, Michael.Hennerich@analog.com, jic23@kernel.org Cc: linux-iio@vger.kernel.org, linux-kernel@vger.kernel.org, eraretuya@gmail.com, l.rubusch@gmail.com Subject: [PATCH v5 05/11] iio: accel: adxl345: add freefall feature Date: Tue, 18 Mar 2025 23:08:37 +0000 Message-Id: <20250318230843.76068-6-l.rubusch@gmail.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250318230843.76068-1-l.rubusch@gmail.com> References: <20250318230843.76068-1-l.rubusch@gmail.com> Precedence: bulk X-Mailing-List: linux-iio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Add the freefall detection of the sensor together with a threshold and time parameter. A freefall event is detected if the measuring signal falls below the threshold. Introduce a freefall threshold stored in regmap cache, and a freefall time, having the scaled time value stored as a member variable in the state instance. Signed-off-by: Lothar Rubusch --- drivers/iio/accel/adxl345_core.c | 126 +++++++++++++++++++++++++++++++ 1 file changed, 126 insertions(+) diff --git a/drivers/iio/accel/adxl345_core.c b/drivers/iio/accel/adxl345_core.c index 52daf46c4acd..76ee657e958a 100644 --- a/drivers/iio/accel/adxl345_core.c +++ b/drivers/iio/accel/adxl345_core.c @@ -75,6 +75,7 @@ struct adxl345_state { u32 tap_duration_us; u32 tap_latent_us; u32 tap_window_us; + u32 ff_time_ms; __le16 fifo_buf[ADXL345_DIRS * ADXL345_FIFO_SIZE + 1] __aligned(IIO_DMA_MINALIGN); }; @@ -96,6 +97,14 @@ static struct iio_event_spec adxl345_events[] = { BIT(IIO_EV_INFO_RESET_TIMEOUT) | BIT(IIO_EV_INFO_TAP2_MIN_DELAY), }, + { + /* free fall */ + .type = IIO_EV_TYPE_MAG, + .dir = IIO_EV_DIR_FALLING, + .mask_shared_by_type = BIT(IIO_EV_INFO_ENABLE) | + BIT(IIO_EV_INFO_VALUE) | + BIT(IIO_EV_INFO_PERIOD), + }, }; #define ADXL345_CHANNEL(index, reg, axis) { \ @@ -376,6 +385,64 @@ static int adxl345_set_tap_latent(struct adxl345_state *st, u32 val_int, return _adxl345_set_tap_time(st, ADXL345_TAP_TIME_LATENT, val_fract_us); } +/* freefall */ + +static int adxl345_is_ff_en(struct adxl345_state *st, bool *en) +{ + int ret; + unsigned int regval; + + ret = regmap_read(st->regmap, ADXL345_REG_INT_ENABLE, ®val); + if (ret) + return ret; + + *en = FIELD_GET(ADXL345_INT_FREE_FALL, regval) > 0; + + return 0; +} + +static int adxl345_set_ff_en(struct adxl345_state *st, bool cmd_en) +{ + unsigned int regval, ff_threshold; + const unsigned int freefall_mask = 0x02; + bool en; + int ret; + + ret = regmap_read(st->regmap, ADXL345_REG_THRESH_FF, &ff_threshold); + if (ret) + return ret; + + en = cmd_en && ff_threshold > 0 && st->ff_time_ms > 0; + + regval = en ? ADXL345_INT_FREE_FALL : 0x00; + + return regmap_update_bits(st->regmap, ADXL345_REG_INT_ENABLE, + freefall_mask, regval); +} + +static int adxl345_set_ff_time(struct adxl345_state *st, u32 val_int, + u32 val_fract_us) +{ + unsigned int regval; + int val_ms; + + /* + * max value is 255 * 5000 us = 1.275000 seconds + * + * Note: the scaling is similar to the scaling in the ADXL380 + */ + if (1000000 * val_int + val_fract_us > 1275000) + return -EINVAL; + + val_ms = val_int * 1000 + DIV_ROUND_UP(val_fract_us, 1000); + st->ff_time_ms = val_ms; + + regval = DIV_ROUND_CLOSEST(val_ms, 5); + + /* Values between 100ms and 350ms (0x14 to 0x46) are recommended. */ + return regmap_write(st->regmap, ADXL345_REG_TIME_FF, min(regval, 0xff)); +} + static int adxl345_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask) @@ -488,6 +555,11 @@ static int adxl345_read_event_config(struct iio_dev *indio_dev, default: return -EINVAL; } + case IIO_EV_TYPE_MAG: + ret = adxl345_is_ff_en(st, &int_en); + if (ret) + return ret; + return int_en; default: return -EINVAL; } @@ -511,6 +583,8 @@ static int adxl345_write_event_config(struct iio_dev *indio_dev, default: return -EINVAL; } + case IIO_EV_TYPE_MAG: + return adxl345_set_ff_en(st, state); default: return -EINVAL; } @@ -525,6 +599,7 @@ static int adxl345_read_event_value(struct iio_dev *indio_dev, { struct adxl345_state *st = iio_priv(indio_dev); unsigned int tap_threshold; + unsigned int ff_threshold; int ret; switch (type) { @@ -558,6 +633,22 @@ static int adxl345_read_event_value(struct iio_dev *indio_dev, default: return -EINVAL; } + case IIO_EV_TYPE_MAG: + switch (info) { + case IIO_EV_INFO_VALUE: + ret = regmap_read(st->regmap, ADXL345_REG_THRESH_FF, + &ff_threshold); + if (ret) + return ret; + *val = ff_threshold; + return IIO_VAL_INT; + case IIO_EV_INFO_PERIOD: + *val = st->ff_time_ms; + *val2 = 1000; + return IIO_VAL_FRACTIONAL; + default: + return -EINVAL; + } default: return -EINVAL; } @@ -605,6 +696,22 @@ static int adxl345_write_event_value(struct iio_dev *indio_dev, return -EINVAL; } break; + case IIO_EV_TYPE_MAG: + switch (info) { + case IIO_EV_INFO_VALUE: + ret = regmap_write(st->regmap, ADXL345_REG_THRESH_FF, val); + if (ret) + return ret; + break; + case IIO_EV_INFO_PERIOD: + ret = adxl345_set_ff_time(st, val, val2); + if (ret) + return ret; + break; + default: + return -EINVAL; + } + break; default: return -EINVAL; } @@ -858,6 +965,17 @@ static int adxl345_push_event(struct iio_dev *indio_dev, int int_stat, return ret; } + if (FIELD_GET(ADXL345_INT_FREE_FALL, int_stat)) { + ret = iio_push_event(indio_dev, + IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, + IIO_MOD_X_OR_Y_OR_Z, + IIO_EV_TYPE_MAG, + IIO_EV_DIR_FALLING), + ts); + if (ret) + return ret; + } + if (FIELD_GET(ADXL345_INT_WATERMARK, int_stat)) { samples = adxl345_get_samples(st); if (samples < 0) @@ -966,6 +1084,7 @@ int adxl345_core_probe(struct device *dev, struct regmap *regmap, ADXL345_DATA_FORMAT_FULL_RES | ADXL345_DATA_FORMAT_SELF_TEST); unsigned int tap_threshold; + unsigned int ff_threshold; int ret; indio_dev = devm_iio_device_alloc(dev, sizeof(*st)); @@ -985,6 +1104,9 @@ int adxl345_core_probe(struct device *dev, struct regmap *regmap, st->tap_window_us = 64; /* 64 [0x40] -> .080 */ st->tap_latent_us = 16; /* 16 [0x10] -> .020 */ + ff_threshold = 8; /* 8 [0x08] */ + st->ff_time_ms = 32; /* 32 [0x20] -> 0.16 */ + indio_dev->name = st->info->name; indio_dev->info = &adxl345_info; indio_dev->modes = INDIO_DIRECT_MODE; @@ -1061,6 +1183,10 @@ int adxl345_core_probe(struct device *dev, struct regmap *regmap, if (ret) return ret; + ret = regmap_write(st->regmap, ADXL345_REG_THRESH_FF, ff_threshold); + if (ret) + return ret; + /* FIFO_STREAM mode is going to be activated later */ ret = devm_iio_kfifo_buffer_setup(dev, indio_dev, &adxl345_buffer_ops); if (ret) From patchwork Tue Mar 18 23:08:38 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lothar Rubusch X-Patchwork-Id: 14021719 Received: from mail-wr1-f54.google.com (mail-wr1-f54.google.com [209.85.221.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 2A3AA2144B1; Tue, 18 Mar 2025 23:09:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.54 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742339345; cv=none; b=ewE85p3cRCFpwugzDOAK9NkFyRoQrmeZugMxKcOPmGWKWifQk4xlhDKCHLdRK3CvDNFwuPMIEGMgNXyxvYx/Qin1SLjwXxUyVU2+g63NRkW+ThjGEx88NaZYu9H7OfjLJxZ4dex9Co69ACo+nIYE/X33d8uKDjKyhp8NveZJiVk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742339345; c=relaxed/simple; bh=Z/7VEuRgOA4BeT0MtcRBUAMc9NIeD8gJBNj7blBoYZw=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=Z1RDdDXlNHcr7dR7E8u/DLsQNZXG2ujSuh0nEsNyNYvKLf7i4re5wHPXEssuCyvc9ooJSW5Hw48IYB0DZjgpHEOwvq93zngvCPdJPBerymWQUTjGyCIkW2cGbTVKnWVmCt9jArxAo7vR9vKR+6KQz+or57yaLi2BQbidbdKe5YM= 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=nL0cSOPl; arc=none smtp.client-ip=209.85.221.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="nL0cSOPl" Received: by mail-wr1-f54.google.com with SMTP id ffacd0b85a97d-39123d2eb7fso810089f8f.1; Tue, 18 Mar 2025 16:09:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1742339341; x=1742944141; 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=Y1wV9l2Uzry3Uz72goIHkiQUrIB+sI2UJzYpFon7R0s=; b=nL0cSOPlVbM8nESWFY9Y0s1FRTs7ceGTu/MJyJPb53JcmPoP3twzZQQWsN+PwT4Wgk dCF61HYjEuG9LctHjVIgNlVFkJS3CGJi5lcUOsy34fklkYzTMLklzh4sW3Ob4n/DLqHH pY90zQW6cO9zErWZ8t+UQ7nr5Bs+nmZE6wD4pVlnNXmRuXgKHDdC7tVrAXXBexwj9iOe WSFBW57X8UHuCupnqWZNlDGveHzoorwPXSmjYYjk9f+2T36+gPcpdcDVgsfikFj8714U fSCoFSCwedLx1xXHncW6dFgYv84K/wLCGRDN6HwFRPaVkBO0QQDO/Rc4D7S9/D7laYqa m4iQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1742339341; x=1742944141; 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=Y1wV9l2Uzry3Uz72goIHkiQUrIB+sI2UJzYpFon7R0s=; b=JQQ0lvfbYEW42yMtCL7biwycX4vE3n9zyFlAkNzVNs18LCfkpVO5YXQbpbUsQOvVrt sRuPcMaokQa5EDxuo/o25FmTJ5fFSevM9pdWsqBi4lLf/NJeryTdg4unzh52InalvYML 5SKAHCtMV5gNvb7VAOOQyM02YuPte4gKMBuIJBGHjkWj9hwroUHzHsK60CJtldEoQls0 /GYHSr/oMmgxdlpFoyFHkPm8o+k2Hea7h3a2Bga2fPKNMNawZMBE8h+MqJjoDzDtJDcM mobj8kKnyTTZ94ZWezindnUeNvzyh7i7zR51DBWCHKSNuyPvT72zCfI0IUVZEwbo/k58 MSbA== X-Forwarded-Encrypted: i=1; AJvYcCWD00lL+mqNfcsjaldZl9TV/p8nt92w2HfPPTU9DvsbHOf91FJNJprofd4mS/N3EqcL/nVk7KFqZ5c3rqI=@vger.kernel.org X-Gm-Message-State: AOJu0YzguGNedqQpoLMnCle6L2+OiaH+FEtNBy9vXnVmIj8bMF8NuWTw zAjYGGl7bc1sPsuthMmpHnuV7YGj472I4loO2hf30YTPPLo9XWw+ X-Gm-Gg: ASbGncuVlPgtw8AfA8KcZbNdXdXxSwgDJf8ZLy5T6SG4o/eG53B3jykTUvDKoS3prv7 iYx0vs6a6ZP2sofD3Oq+FAvBeEiKYfnKk3T3yQdl3xKkal/mgt7+XT5R/Ff98qCH4lbvlgCpuWz Z9G2ISY7nBoGsb657SnwBuQVaQ+OP9dySHE0Jn7QYNI3s2G+gF83+vYphvz4Daar+gQ+aEdxgOb OFvDliIKBX5TT0jb/Cb4aX2o4iIBLAmXxnFuD2JvorJrfA9scm4XJevkxvBYpBATEx431FH7RV4 bgfXRACCMB7IvTIH5oWIUnCO6ZfPPUxjcEZeSaL/RcolqJMD7aX/SHrwISJaHGiKspv4H6DZZfy gz7PWxvFI2VnjkJ0x5qW3wiA= X-Google-Smtp-Source: AGHT+IFnyJ9D21A59ybLpqqtdGLcbZmI5RbP7x/4Y7aeWCysMoSTP4RfJpcxC6R5ypU7iFPTHQn2FA== X-Received: by 2002:a05:6000:2a1:b0:38d:dee1:e2d2 with SMTP id ffacd0b85a97d-399739ca882mr201582f8f.2.1742339341206; Tue, 18 Mar 2025 16:09:01 -0700 (PDT) Received: from 0e1b0684397b.v.cablecom.net (84-72-156-211.dclient.hispeed.ch. [84.72.156.211]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-43d440ed793sm1113455e9.39.2025.03.18.16.08.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 18 Mar 2025 16:09:00 -0700 (PDT) From: Lothar Rubusch To: lars@metafoo.de, Michael.Hennerich@analog.com, jic23@kernel.org Cc: linux-iio@vger.kernel.org, linux-kernel@vger.kernel.org, eraretuya@gmail.com, l.rubusch@gmail.com Subject: [PATCH v5 06/11] iio: accel: adxl345: extend sample frequency adjustments Date: Tue, 18 Mar 2025 23:08:38 +0000 Message-Id: <20250318230843.76068-7-l.rubusch@gmail.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250318230843.76068-1-l.rubusch@gmail.com> References: <20250318230843.76068-1-l.rubusch@gmail.com> Precedence: bulk X-Mailing-List: linux-iio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Introduce enums and functions to work with the sample frequency adjustments. Let the sample frequency adjust via IIO and configure a reasonable default. Replace the old static sample frequency handling. During adjustment of bw registers, measuring is disabled and afterwards enabled again. Signed-off-by: Lothar Rubusch --- drivers/iio/accel/adxl345.h | 2 +- drivers/iio/accel/adxl345_core.c | 150 ++++++++++++++++++++++++------- 2 files changed, 118 insertions(+), 34 deletions(-) diff --git a/drivers/iio/accel/adxl345.h b/drivers/iio/accel/adxl345.h index 7d482dd595fa..6c1f96406136 100644 --- a/drivers/iio/accel/adxl345.h +++ b/drivers/iio/accel/adxl345.h @@ -69,7 +69,7 @@ * BW_RATE bits - Bandwidth and output data rate. The default value is * 0x0A, which translates to a 100 Hz output data rate */ -#define ADXL345_BW_RATE GENMASK(3, 0) +#define ADXL345_BW_RATE_MSK GENMASK(3, 0) #define ADXL345_BW_LOW_POWER BIT(4) #define ADXL345_BASE_RATE_NANO_HZ 97656250LL diff --git a/drivers/iio/accel/adxl345_core.c b/drivers/iio/accel/adxl345_core.c index 76ee657e958a..d9d786e15156 100644 --- a/drivers/iio/accel/adxl345_core.c +++ b/drivers/iio/accel/adxl345_core.c @@ -64,6 +64,45 @@ static const unsigned int adxl345_tap_time_reg[] = { [ADXL345_TAP_TIME_DUR] = ADXL345_REG_DUR, }; +enum adxl345_odr { + ADXL345_ODR_0P10HZ = 0, + ADXL345_ODR_0P20HZ, + ADXL345_ODR_0P39HZ, + ADXL345_ODR_0P78HZ, + ADXL345_ODR_1P56HZ, + ADXL345_ODR_3P13HZ, + ADXL345_ODR_6P25HZ, + ADXL345_ODR_12P50HZ, + ADXL345_ODR_25HZ, + ADXL345_ODR_50HZ, + ADXL345_ODR_100HZ, + ADXL345_ODR_200HZ, + ADXL345_ODR_400HZ, + ADXL345_ODR_800HZ, + ADXL345_ODR_1600HZ, + ADXL345_ODR_3200HZ, +}; + +/* Certain features recommend 12.5 Hz - 400 Hz ODR */ +static const int adxl345_odr_tbl[][2] = { + [ADXL345_ODR_0P10HZ] = { 0, 97000 }, + [ADXL345_ODR_0P20HZ] = { 0, 195000 }, + [ADXL345_ODR_0P39HZ] = { 0, 390000 }, + [ADXL345_ODR_0P78HZ] = { 0, 781000 }, + [ADXL345_ODR_1P56HZ] = { 1, 562000 }, + [ADXL345_ODR_3P13HZ] = { 3, 125000 }, + [ADXL345_ODR_6P25HZ] = { 6, 250000 }, + [ADXL345_ODR_12P50HZ] = { 12, 500000 }, + [ADXL345_ODR_25HZ] = { 25, 0 }, + [ADXL345_ODR_50HZ] = { 50, 0 }, + [ADXL345_ODR_100HZ] = { 100, 0 }, + [ADXL345_ODR_200HZ] = { 200, 0 }, + [ADXL345_ODR_400HZ] = { 400, 0 }, + [ADXL345_ODR_800HZ] = { 800, 0 }, + [ADXL345_ODR_1600HZ] = { 1600, 0 }, + [ADXL345_ODR_3200HZ] = { 3200, 0 }, +}; + struct adxl345_state { const struct adxl345_chip_info *info; struct regmap *regmap; @@ -116,6 +155,7 @@ static struct iio_event_spec adxl345_events[] = { BIT(IIO_CHAN_INFO_CALIBBIAS), \ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ .scan_index = (index), \ .scan_type = { \ .sign = 's', \ @@ -443,14 +483,53 @@ static int adxl345_set_ff_time(struct adxl345_state *st, u32 val_int, return regmap_write(st->regmap, ADXL345_REG_TIME_FF, min(regval, 0xff)); } +static int adxl345_find_odr(struct adxl345_state *st, int val, + int val2, enum adxl345_odr *odr) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(adxl345_odr_tbl); i++) { + if (val == adxl345_odr_tbl[i][0] && + val2 == adxl345_odr_tbl[i][1]) { + *odr = i; + return 0; + } + } + + return -EINVAL; +} + +static int adxl345_set_odr(struct adxl345_state *st, enum adxl345_odr odr) +{ + return regmap_update_bits(st->regmap, ADXL345_REG_BW_RATE, + ADXL345_BW_RATE_MSK, + FIELD_PREP(ADXL345_BW_RATE_MSK, odr)); +} + +static int adxl345_read_avail(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + const int **vals, int *type, + int *length, long mask) +{ + switch (mask) { + case IIO_CHAN_INFO_SAMP_FREQ: + *vals = (int *)adxl345_odr_tbl; + *type = IIO_VAL_INT_PLUS_MICRO; + *length = ARRAY_SIZE(adxl345_odr_tbl) * 2; + return IIO_AVAIL_LIST; + } + + return -EINVAL; +} + static int adxl345_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask) { struct adxl345_state *st = iio_priv(indio_dev); __le16 accel; - long long samp_freq_nhz; unsigned int regval; + enum adxl345_odr odr; int ret; switch (mask) { @@ -488,12 +567,10 @@ static int adxl345_read_raw(struct iio_dev *indio_dev, ret = regmap_read(st->regmap, ADXL345_REG_BW_RATE, ®val); if (ret) return ret; - - samp_freq_nhz = ADXL345_BASE_RATE_NANO_HZ << - (regval & ADXL345_BW_RATE); - *val = div_s64_rem(samp_freq_nhz, NANOHZ_PER_HZ, val2); - - return IIO_VAL_INT_PLUS_NANO; + odr = FIELD_GET(ADXL345_BW_RATE_MSK, regval); + *val = adxl345_odr_tbl[odr][0]; + *val2 = adxl345_odr_tbl[odr][1]; + return IIO_VAL_INT_PLUS_MICRO; } return -EINVAL; @@ -504,7 +581,12 @@ static int adxl345_write_raw(struct iio_dev *indio_dev, int val, int val2, long mask) { struct adxl345_state *st = iio_priv(indio_dev); - s64 n; + enum adxl345_odr odr; + int ret; + + ret = adxl345_set_measure_en(st, false); + if (ret) + return ret; switch (mask) { case IIO_CHAN_INFO_CALIBBIAS: @@ -512,20 +594,26 @@ static int adxl345_write_raw(struct iio_dev *indio_dev, * 8-bit resolution at +/- 2g, that is 4x accel data scale * factor */ - return regmap_write(st->regmap, - ADXL345_REG_OFS_AXIS(chan->address), - val / 4); + ret = regmap_write(st->regmap, + ADXL345_REG_OFS_AXIS(chan->address), + val / 4); + if (ret) + return ret; + break; case IIO_CHAN_INFO_SAMP_FREQ: - n = div_s64(val * NANOHZ_PER_HZ + val2, - ADXL345_BASE_RATE_NANO_HZ); + ret = adxl345_find_odr(st, val, val2, &odr); + if (ret) + return ret; - return regmap_update_bits(st->regmap, ADXL345_REG_BW_RATE, - ADXL345_BW_RATE, - clamp_val(ilog2(n), 0, - ADXL345_BW_RATE)); + ret = adxl345_set_odr(st, odr); + if (ret) + return ret; + break; + default: + return -EINVAL; } - return -EINVAL; + return adxl345_set_measure_en(st, true); } static int adxl345_read_event_config(struct iio_dev *indio_dev, @@ -754,7 +842,7 @@ static int adxl345_write_raw_get_fmt(struct iio_dev *indio_dev, case IIO_CHAN_INFO_CALIBBIAS: return IIO_VAL_INT; case IIO_CHAN_INFO_SAMP_FREQ: - return IIO_VAL_INT_PLUS_NANO; + return IIO_VAL_INT_PLUS_MICRO; default: return -EINVAL; } @@ -767,19 +855,6 @@ static void adxl345_powerdown(void *ptr) adxl345_set_measure_en(st, false); } -static IIO_CONST_ATTR_SAMP_FREQ_AVAIL( -"0.09765625 0.1953125 0.390625 0.78125 1.5625 3.125 6.25 12.5 25 50 100 200 400 800 1600 3200" -); - -static struct attribute *adxl345_attrs[] = { - &iio_const_attr_sampling_frequency_available.dev_attr.attr, - NULL -}; - -static const struct attribute_group adxl345_attrs_group = { - .attrs = adxl345_attrs, -}; - static int adxl345_set_fifo(struct adxl345_state *st) { unsigned int intio; @@ -1042,9 +1117,9 @@ static irqreturn_t adxl345_irq_handler(int irq, void *p) } static const struct iio_info adxl345_info = { - .attrs = &adxl345_attrs_group, .read_raw = adxl345_read_raw, .write_raw = adxl345_write_raw, + .read_avail = adxl345_read_avail, .write_raw_get_fmt = adxl345_write_raw_get_fmt, .read_event_config = adxl345_read_event_config, .write_event_config = adxl345_write_event_config, @@ -1114,6 +1189,15 @@ int adxl345_core_probe(struct device *dev, struct regmap *regmap, indio_dev->num_channels = ARRAY_SIZE(adxl345_channels); indio_dev->available_scan_masks = adxl345_scan_masks; + /* + * Using I2C at 100kHz would limit the maximum ODR to 200Hz, operation + * at an output rate above the recommended maximum may result in + * undesired behavior. + */ + ret = adxl345_set_odr(st, ADXL345_ODR_200HZ); + if (ret) + return ret; + /* Reset interrupts at start up */ ret = regmap_write(st->regmap, ADXL345_REG_INT_ENABLE, 0x00); if (ret) From patchwork Tue Mar 18 23:08:39 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lothar Rubusch X-Patchwork-Id: 14021720 Received: from mail-wm1-f54.google.com (mail-wm1-f54.google.com [209.85.128.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 917D12147EA; Tue, 18 Mar 2025 23:09:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.54 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742339346; cv=none; b=P5I8FxNle3TVAWZCVbedq7VufQMz4s3sNSWvue87uEyaFDnNzinoXkrzd6SYiHvwymWq1Yb2lnRDJxhT9Qf6Ucgb5Dq1o5UcrAf7MVOWV5sRYVhKaA+fEU1osm+W/X/Qlfw8cRKdKW8pHEk3PSSm9hsNv2jrbxtmOjkGD7iDH0Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742339346; c=relaxed/simple; bh=LrgfFaazNtPCpvrYbWwd696COe/34Tg2puXK+eCx3qU=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=AqBKtX/CflHbdTKjCzPcdTEx+RO4/GW9CdXxzjT+RnIfKiSWi2RunPGb31+SoiWMXj4O1A1QL1i0VAVwjdXgZjz5hx3vnCgXS+qHjXs0oSkhns3vDAyaecZdNn3e04OMLbIa/pwmroa316s4YkaIaYf/B/nPWkpJqXg5doDcPwk= 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=eCn7RKH/; arc=none smtp.client-ip=209.85.128.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="eCn7RKH/" Received: by mail-wm1-f54.google.com with SMTP id 5b1f17b1804b1-43ba8bbeae2so5301125e9.0; Tue, 18 Mar 2025 16:09:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1742339343; x=1742944143; 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=Ny2foABWhgHXyPlG+cE6a95cgoCM9zCjuNRfX70Qcfc=; b=eCn7RKH/FGgxU8Ipf9iPr1jGFPNsBmDZktRfELYDH7lZZCdK2PCGDs58sFhDeQMqxt X7KtVdA1uyk5yRABQTb1uD7BX243BZGwBBlmyJF8uFNWSm/qkB/wKKZFRR49jolLCeO1 WukJi/pGhsDWlL0FtZpLMjW81qxMUQfqVB6peQkqKn49N9GQDoco7IzPcotFaaz3tByK COlOjnqLQ7fWBKPpaGO+LLZo2upHVBcNch5ndpdg6dYw+r2jQNIZkOJFsmAO49rDC55r ifCitOJ7kWedrmOUBhtAx/T353cOxWlnMMrRQGslA9bQQikt4fMQFA5nS8zzBeRDRLu8 bNHQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1742339343; x=1742944143; 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=Ny2foABWhgHXyPlG+cE6a95cgoCM9zCjuNRfX70Qcfc=; b=PbyBlUERye5mYGZ2tOg7hQygGoSfScGb62O/RyDPfibaIR/mFSlpCc342ppw3NpPNu Md50CIXX/7eH9g2Bdk1gl7WMMeCJi7nH5a9vy3/NqQWRgK75Zl4R5pBCRoMpnoa+KslM VGKuyML1cMgPtSHrGcA7LQhASB7gCxpmXfIJkc/YWEAHPWMDdyWYS+Irkkpcie17/e+0 pfV9G0jzu0bBLm9e9VEaEIyy4U48LgD2ofOBp4Ey0dBW1/s6aI4fciIP1stLAZMl59dC qejX7MdpCEhOx3gyPsRCMM9tjiZ/yIF9Tl3PcLseQkDqSaFurRlskE6qOpT6NMolYjxm sJnw== X-Forwarded-Encrypted: i=1; AJvYcCVzLCL2ZjWyR9suKiOumdo1xQE2i6RPa/xo2bGokh0GoktH1vBbJ+7+AK/wg1AUZPl1AUgBH/NX7dk+i8M=@vger.kernel.org X-Gm-Message-State: AOJu0Ywfy/fEn4ozD+4sun0HanjHLstbfDUejlLXMUi7+vM4jBaYnuFV yc8BaRqE6FigsKCVIbFQTpgI208jfxugO1dFPsmnYFKuwOcVnd3m X-Gm-Gg: ASbGncuq7FUnMAKrVxOW2cNcVPSv9c1VpcgnXBN1bHLb7J9GXHJcjZ+cje2fP4NEqGQ lY0LsJI5faMvTCvVZOwIxgNfXKsqklGYfu2qFmGnq01v5HbKJLQKsNip3XIEcxrE9L00SjZLmz5 YqbFdoOa3va2h1/qLpiD8kpnSS+GFu5TysS6ZckJE+hEWug2NoHULRz55sU3RmWovwDLSS7FEnO WzJn4Gy8wekPP0GS75fylSYF8FLi9X9UPVuFfBMcHeGj4PSWOSXhtgRbLrtarlcrS7RM+ZLFzBo Tcll3DaTUYYwdsvn/Mkajr00hMwBlQE3/S27HEldnowVldhHvQnZvRKOTiGqwoZCDnVMEwa0JMA ZfhP7oeSyZuBVQzD7PxaWRg80IASPUlnMbA== X-Google-Smtp-Source: AGHT+IHkPSQRzV4ucWVfwfbAq7agyi8SYS2XEJCXewQiNqeMcGCepJ4DEb9vFwl5SKpRsP5CsHokeA== X-Received: by 2002:a05:600c:4f8b:b0:439:88bb:d00b with SMTP id 5b1f17b1804b1-43d4454b03bmr245705e9.5.1742339342682; Tue, 18 Mar 2025 16:09:02 -0700 (PDT) Received: from 0e1b0684397b.v.cablecom.net (84-72-156-211.dclient.hispeed.ch. [84.72.156.211]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-43d440ed793sm1113455e9.39.2025.03.18.16.09.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 18 Mar 2025 16:09:01 -0700 (PDT) From: Lothar Rubusch To: lars@metafoo.de, Michael.Hennerich@analog.com, jic23@kernel.org Cc: linux-iio@vger.kernel.org, linux-kernel@vger.kernel.org, eraretuya@gmail.com, l.rubusch@gmail.com Subject: [PATCH v5 07/11] iio: accel: adxl345: add g-range configuration Date: Tue, 18 Mar 2025 23:08:39 +0000 Message-Id: <20250318230843.76068-8-l.rubusch@gmail.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250318230843.76068-1-l.rubusch@gmail.com> References: <20250318230843.76068-1-l.rubusch@gmail.com> Precedence: bulk X-Mailing-List: linux-iio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Introduce a mechanism to be able to configure and work with the available g-ranges keeping the precision of 13 digits. Signed-off-by: Lothar Rubusch --- drivers/iio/accel/adxl345_core.c | 90 ++++++++++++++++++++++++++++++-- 1 file changed, 87 insertions(+), 3 deletions(-) diff --git a/drivers/iio/accel/adxl345_core.c b/drivers/iio/accel/adxl345_core.c index d9d786e15156..2ba77f31c3a0 100644 --- a/drivers/iio/accel/adxl345_core.c +++ b/drivers/iio/accel/adxl345_core.c @@ -83,6 +83,13 @@ enum adxl345_odr { ADXL345_ODR_3200HZ, }; +enum adxl345_range { + ADXL345_2G_RANGE = 0, + ADXL345_4G_RANGE, + ADXL345_8G_RANGE, + ADXL345_16G_RANGE, +}; + /* Certain features recommend 12.5 Hz - 400 Hz ODR */ static const int adxl345_odr_tbl[][2] = { [ADXL345_ODR_0P10HZ] = { 0, 97000 }, @@ -103,6 +110,33 @@ static const int adxl345_odr_tbl[][2] = { [ADXL345_ODR_3200HZ] = { 3200, 0 }, }; +/* + * Full resolution frequency table: + * (g * 2 * 9.80665) / (2^(resolution) - 1) + * + * resolution := 13 (full) + * g := 2|4|8|16 + * + * 2g at 13bit: 0.004789 + * 4g at 13bit: 0.009578 + * 8g at 13bit: 0.019156 + * 16g at 16bit: 0.038312 + */ +static const int adxl345_fullres_range_tbl[][2] = { + [ADXL345_2G_RANGE] = { 0, 4789 }, + [ADXL345_4G_RANGE] = { 0, 9578 }, + [ADXL345_8G_RANGE] = { 0, 19156 }, + [ADXL345_16G_RANGE] = { 0, 38312 }, +}; + +/* scaling */ +static const int adxl345_range_factor_tbl[] = { + [ADXL345_2G_RANGE] = 1, + [ADXL345_4G_RANGE] = 2, + [ADXL345_8G_RANGE] = 4, + [ADXL345_16G_RANGE] = 8, +}; + struct adxl345_state { const struct adxl345_chip_info *info; struct regmap *regmap; @@ -155,7 +189,8 @@ static struct iio_event_spec adxl345_events[] = { BIT(IIO_CHAN_INFO_CALIBBIAS), \ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ BIT(IIO_CHAN_INFO_SAMP_FREQ), \ - .info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_SCALE) | \ + BIT(IIO_CHAN_INFO_SAMP_FREQ), \ .scan_index = (index), \ .scan_type = { \ .sign = 's', \ @@ -506,12 +541,40 @@ static int adxl345_set_odr(struct adxl345_state *st, enum adxl345_odr odr) FIELD_PREP(ADXL345_BW_RATE_MSK, odr)); } +static int adxl345_find_range(struct adxl345_state *st, int val, int val2, + enum adxl345_range *range) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(adxl345_fullres_range_tbl); i++) { + if (val == adxl345_fullres_range_tbl[i][0] && + val2 == adxl345_fullres_range_tbl[i][1]) { + *range = i; + return 0; + } + } + + return -EINVAL; +} + +static int adxl345_set_range(struct adxl345_state *st, enum adxl345_range range) +{ + return regmap_update_bits(st->regmap, ADXL345_REG_DATA_FORMAT, + ADXL345_DATA_FORMAT_RANGE, + FIELD_PREP(ADXL345_DATA_FORMAT_RANGE, range)); +} + static int adxl345_read_avail(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, const int **vals, int *type, int *length, long mask) { switch (mask) { + case IIO_CHAN_INFO_SCALE: + *vals = (int *)adxl345_fullres_range_tbl; + *type = IIO_VAL_INT_PLUS_MICRO; + *length = ARRAY_SIZE(adxl345_fullres_range_tbl) * 2; + return IIO_AVAIL_LIST; case IIO_CHAN_INFO_SAMP_FREQ: *vals = (int *)adxl345_odr_tbl; *type = IIO_VAL_INT_PLUS_MICRO; @@ -530,6 +593,7 @@ static int adxl345_read_raw(struct iio_dev *indio_dev, __le16 accel; unsigned int regval; enum adxl345_odr odr; + enum adxl345_range range; int ret; switch (mask) { @@ -548,8 +612,12 @@ static int adxl345_read_raw(struct iio_dev *indio_dev, *val = sign_extend32(le16_to_cpu(accel), 12); return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: - *val = 0; - *val2 = st->info->uscale; + ret = regmap_read(st->regmap, ADXL345_REG_DATA_FORMAT, ®val); + if (ret) + return ret; + range = FIELD_GET(ADXL345_DATA_FORMAT_RANGE, regval); + *val = adxl345_fullres_range_tbl[range][0]; + *val2 = adxl345_fullres_range_tbl[range][1]; return IIO_VAL_INT_PLUS_MICRO; case IIO_CHAN_INFO_CALIBBIAS: ret = regmap_read(st->regmap, @@ -581,6 +649,7 @@ static int adxl345_write_raw(struct iio_dev *indio_dev, int val, int val2, long mask) { struct adxl345_state *st = iio_priv(indio_dev); + enum adxl345_range range; enum adxl345_odr odr; int ret; @@ -609,6 +678,15 @@ static int adxl345_write_raw(struct iio_dev *indio_dev, if (ret) return ret; break; + case IIO_CHAN_INFO_SCALE: + ret = adxl345_find_range(st, val, val2, &range); + if (ret) + return ret; + + ret = adxl345_set_range(st, range); + if (ret) + return ret; + break; default: return -EINVAL; } @@ -841,6 +919,8 @@ static int adxl345_write_raw_get_fmt(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_CALIBBIAS: return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + return IIO_VAL_INT_PLUS_MICRO; case IIO_CHAN_INFO_SAMP_FREQ: return IIO_VAL_INT_PLUS_MICRO; default: @@ -1198,6 +1278,10 @@ int adxl345_core_probe(struct device *dev, struct regmap *regmap, if (ret) return ret; + ret = adxl345_set_range(st, ADXL345_16G_RANGE); + if (ret) + return ret; + /* Reset interrupts at start up */ ret = regmap_write(st->regmap, ADXL345_REG_INT_ENABLE, 0x00); if (ret) From patchwork Tue Mar 18 23:08:40 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lothar Rubusch X-Patchwork-Id: 14021721 Received: from mail-wr1-f53.google.com (mail-wr1-f53.google.com [209.85.221.53]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0104D21504E; Tue, 18 Mar 2025 23:09:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.53 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742339349; cv=none; b=uZ7dJJaA1snWfrNx2+NdetW8BYwcNCkw1cIU21X2uQsIrVOrdj5OIs5Aq+dFSeuyxTaJOTbsyQAbEc1xzgvTN+nyIXDBYfUJduyfBMJ2YVc5Ars2kqJGR5lAu4RxuNOpP01rNT8OIIL4zHMhsRGa29HUD1IclF86h+OvqrPS4i8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742339349; c=relaxed/simple; bh=RVR3zu+KfVpUgL3tdC4QLemoM5TIYvYAsCe4gVAhl+c=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=XCWn6uVpy7yFYXy4SqNA9kTOTSIEv+Zufk05MoKcLptPPsbep0RrW1vVswuJyfciDfhjFW3RdgUh+oX9qlUuD5uZFts7J81x8ibhw6/MpeoM71SWfoYASsnX2D80iPZT+s1lrqUWPhqpFNsz6+RpW9uinAJW0Q1IsgBMUDVYkcY= 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=atYGaiKp; arc=none smtp.client-ip=209.85.221.53 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="atYGaiKp" Received: by mail-wr1-f53.google.com with SMTP id ffacd0b85a97d-39973c72e8cso23685f8f.0; Tue, 18 Mar 2025 16:09:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1742339344; x=1742944144; 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=0MxxWAHFgtZ5hBiQ9O6m5AIG2XO+clsclDewmbmkb1Q=; b=atYGaiKpYJidHuAzn8GF4dRfZAr0vrZj97rL7QnFSSdX/0rQXCLb0GTWUQcK2w56AK x+ueQf2j2uQ9GvpATsoSOCoohfe42xlqlEt607He2y6O1aDEWR3w4ZF8g/cSePj5IMJ9 klaAwT4k9AJ7RZXEiwP+B5kEv89bXcneVF7WUSNvWG1LsQ25nVZcaeRA5Dwp/mBOH9xg EW/0cFWTzncpQpeYY5uA99aV2sU1cbreXH/3CrXY8P0Mp1byTqGU3JqHrX+9R2bIsfP4 DyF85FF2YhJZMt3zi7TvkQq6Zi34UsOZ5le/VZHYK1i3o3fTjOaPEMVrqTkYy5BG4kFC cDSA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1742339344; x=1742944144; 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=0MxxWAHFgtZ5hBiQ9O6m5AIG2XO+clsclDewmbmkb1Q=; b=B+8rdISjCyEB4bagMf9NcWspjtpXVLZNGitGSBSJTjIoVBnISCHxsBuusykgtIp6LY s5mIKIU2PjpqrYkh5JSy+3QDRnGY96/SD+64/DvACeB8BedHoU4q48G3HJobYf5xfEW+ jjNWWl5ZvuzAkNaJIPzE/uQEczlzPxCFToyf0N372eKAKSjIg8WKKLb+j20fw7wFSstz XkbxjwAlS3sZxHyucYHUBIPQF9vC8YJK+ywnjZ+Th9Go97SFGRdrCrXPkHMGvO1X0xDH YpF7PfkatPMf/L0YN8kucPrpErFUrxcL7f5FbZo0NsiuYh/l7v3ctE1KNSGPKHYEZJGL /fig== X-Forwarded-Encrypted: i=1; AJvYcCVa+jH4PT/Jfyl6MIERF063MmgEEAXWsRbPN0HGUbyF3L0+5KcQzrmvoAqoe/PqDqzZxWRJO4rdhNPIOiA=@vger.kernel.org X-Gm-Message-State: AOJu0YwbtzBAGTVTLNfoU0h3j/7Y/tw31Z+sKcDpl2paF1yVRLY1qaY7 4mvC+sHF9vP1OIJ+XWM7GR20BguWPRB7+h/OHDfZv4wHuwu6eqCf X-Gm-Gg: ASbGncsYPuPGZpXEL2q9wu3wc0P2jFNAfAMAameX0KQ+P50YFNISpkPrO0epRxEFIf9 +tZ/39aCVQl4yBoO4HaRdotSmW6b7efPhqkDr1wUIsRlIY314uuoKoDNxLwyiV068kCx0xEJhgV Kdr+mJhcmIE7CklwESTX0lLkHqvW1mtYw0+s9+QH0d9g2xggMhAt+8s4KguJIoqYL2/1ItOlVc9 2adp7jUVJ2A1UYXK2f8SzuwaRtKp8RiU0sJbZ2LdJwrLKJKzW3pbK5V6eUAdyXRIs6Tlm2xJsKe Uplm/4A2Og1C/amBRMucA5lMp0OdV2SVs3Gvqb4NosfeVVBFMQgFVuXNX/nMhHmFxsGGWmb06PP pzjNqqmA5Vwoy+8pqjs9C9Yc= X-Google-Smtp-Source: AGHT+IFbLpLERbrnwjMKdeBkNF8KKBZypHzQEZv7hyct3CaYbSrPm966Rch2KFbwovpFWDCzYWWOog== X-Received: by 2002:a05:600c:3503:b0:43d:2318:ed7f with SMTP id 5b1f17b1804b1-43d436c8322mr1185945e9.0.1742339343978; Tue, 18 Mar 2025 16:09:03 -0700 (PDT) Received: from 0e1b0684397b.v.cablecom.net (84-72-156-211.dclient.hispeed.ch. [84.72.156.211]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-43d440ed793sm1113455e9.39.2025.03.18.16.09.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 18 Mar 2025 16:09:03 -0700 (PDT) From: Lothar Rubusch To: lars@metafoo.de, Michael.Hennerich@analog.com, jic23@kernel.org Cc: linux-iio@vger.kernel.org, linux-kernel@vger.kernel.org, eraretuya@gmail.com, l.rubusch@gmail.com Subject: [PATCH v5 08/11] iio: accel: adxl345: add activity event feature Date: Tue, 18 Mar 2025 23:08:40 +0000 Message-Id: <20250318230843.76068-9-l.rubusch@gmail.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250318230843.76068-1-l.rubusch@gmail.com> References: <20250318230843.76068-1-l.rubusch@gmail.com> Precedence: bulk X-Mailing-List: linux-iio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Make the sensor detect and issue interrupts at activity. Activity events are configured by a threshold stored in regmap cache. Initialize the activity threshold register to a reasonable default value in probe. The value is taken from the older ADXL345 input driver, to provide a similar behavior. Reset the activity/inactivity direction enabling register in probe. Reset and initialization shall bring the sensor in a defined initial state to prevent dangling settings when warm restarting the sensor. Activity, ODR configuration together with the range setting prepare the activity/inactivity hystersesis setup, implemented in a follow up patch. Signed-off-by: Lothar Rubusch --- drivers/iio/accel/adxl345_core.c | 209 ++++++++++++++++++++++++++++++- 1 file changed, 206 insertions(+), 3 deletions(-) diff --git a/drivers/iio/accel/adxl345_core.c b/drivers/iio/accel/adxl345_core.c index 2ba77f31c3a0..6b8491202119 100644 --- a/drivers/iio/accel/adxl345_core.c +++ b/drivers/iio/accel/adxl345_core.c @@ -36,11 +36,16 @@ #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) #define ADXL345_TAP_Z_EN BIT(0) #define ADXL345_TAP_Y_EN BIT(1) #define ADXL345_TAP_X_EN BIT(2) +#define ADXL345_ACT_Z_EN BIT(4) +#define ADXL345_ACT_Y_EN BIT(5) +#define ADXL345_ACT_X_EN BIT(6) + /* single/double tap */ enum adxl345_tap_type { ADXL345_SINGLE_TAP, @@ -64,6 +69,19 @@ static const unsigned int adxl345_tap_time_reg[] = { [ADXL345_TAP_TIME_DUR] = ADXL345_REG_DUR, }; +/* activity/inactivity */ +enum adxl345_activity_type { + ADXL345_ACTIVITY, +}; + +static const unsigned int adxl345_act_int_reg[] = { + [ADXL345_ACTIVITY] = ADXL345_INT_ACTIVITY, +}; + +static const unsigned int adxl345_act_thresh_reg[] = { + [ADXL345_ACTIVITY] = ADXL345_REG_THRESH_ACT, +}; + enum adxl345_odr { ADXL345_ODR_0P10HZ = 0, ADXL345_ODR_0P20HZ, @@ -154,6 +172,13 @@ struct adxl345_state { }; static struct iio_event_spec adxl345_events[] = { + { + /* activity */ + .type = IIO_EV_TYPE_THRESH, + .dir = IIO_EV_DIR_RISING, + .mask_separate = BIT(IIO_EV_INFO_ENABLE), + .mask_shared_by_type = BIT(IIO_EV_INFO_VALUE), + }, { /* single tap */ .type = IIO_EV_TYPE_GESTURE, @@ -256,6 +281,97 @@ static int adxl345_set_measure_en(struct adxl345_state *st, bool en) return regmap_write(st->regmap, ADXL345_REG_POWER_CTL, val); } +/* act/inact */ + +static int adxl345_is_act_inact_en(struct adxl345_state *st, + enum iio_modifier axis, + enum adxl345_activity_type type, bool *en) +{ + unsigned int regval; + bool axis_en; + u32 axis_ctrl; + int ret; + + ret = regmap_read(st->regmap, ADXL345_REG_ACT_INACT_CTRL, &axis_ctrl); + if (ret) + return ret; + + if (type == ADXL345_ACTIVITY) { + switch (axis) { + case IIO_MOD_X: + axis_en = FIELD_GET(ADXL345_ACT_X_EN, axis_ctrl); + break; + case IIO_MOD_Y: + axis_en = FIELD_GET(ADXL345_ACT_Y_EN, axis_ctrl); + break; + case IIO_MOD_Z: + axis_en = FIELD_GET(ADXL345_ACT_Z_EN, axis_ctrl); + break; + default: + return -EINVAL; + } + } + + ret = regmap_read(st->regmap, ADXL345_REG_INT_ENABLE, ®val); + if (ret) + return ret; + + *en = (adxl345_act_int_reg[type] & regval) > 0; + + return 0; +} + +static int adxl345_set_act_inact_en(struct adxl345_state *st, + enum iio_modifier axis, + enum adxl345_activity_type type, + bool cmd_en) +{ + bool axis_en, en; + unsigned int threshold; + u32 axis_ctrl = 0; + int ret; + + if (type == ADXL345_ACTIVITY) { + switch (axis) { + case IIO_MOD_X: + axis_ctrl = ADXL345_ACT_X_EN; + break; + case IIO_MOD_Y: + axis_ctrl = ADXL345_ACT_Y_EN; + break; + case IIO_MOD_Z: + axis_ctrl = ADXL345_ACT_Z_EN; + break; + default: + return -EINVAL; + } + } + + if (cmd_en) + ret = regmap_set_bits(st->regmap, + ADXL345_REG_ACT_INACT_CTRL, axis_ctrl); + else + ret = regmap_clear_bits(st->regmap, + ADXL345_REG_ACT_INACT_CTRL, axis_ctrl); + if (ret) + return ret; + + ret = regmap_read(st->regmap, adxl345_act_thresh_reg[type], &threshold); + if (ret) + return ret; + + en = false; + + if (type == ADXL345_ACTIVITY) { + axis_en = FIELD_GET(ADXL345_REG_ACT_AXIS_MSK, axis_ctrl) > 0; + en = axis_en && threshold > 0; + } + + return regmap_update_bits(st->regmap, ADXL345_REG_INT_ENABLE, + adxl345_act_int_reg[type], + en ? adxl345_act_int_reg[type] : 0); +} + /* tap */ static int _adxl345_set_tap_int(struct adxl345_state *st, @@ -704,6 +820,18 @@ static int adxl345_read_event_config(struct iio_dev *indio_dev, int ret; switch (type) { + case IIO_EV_TYPE_THRESH: + switch (dir) { + case IIO_EV_DIR_RISING: + ret = adxl345_is_act_inact_en(st, chan->channel2, + ADXL345_ACTIVITY, + &int_en); + if (ret) + return ret; + return int_en; + default: + return -EINVAL; + } case IIO_EV_TYPE_GESTURE: switch (dir) { case IIO_EV_DIR_SINGLETAP: @@ -740,6 +868,14 @@ static int adxl345_write_event_config(struct iio_dev *indio_dev, struct adxl345_state *st = iio_priv(indio_dev); switch (type) { + case IIO_EV_TYPE_THRESH: + switch (dir) { + case IIO_EV_DIR_RISING: + return adxl345_set_act_inact_en(st, chan->channel2, + ADXL345_ACTIVITY, state); + default: + return -EINVAL; + } case IIO_EV_TYPE_GESTURE: switch (dir) { case IIO_EV_DIR_SINGLETAP: @@ -764,11 +900,31 @@ static int adxl345_read_event_value(struct iio_dev *indio_dev, int *val, int *val2) { struct adxl345_state *st = iio_priv(indio_dev); + unsigned int act_threshold; unsigned int tap_threshold; unsigned int ff_threshold; int ret; switch (type) { + case IIO_EV_TYPE_THRESH: + switch (info) { + case IIO_EV_INFO_VALUE: + switch (dir) { + case IIO_EV_DIR_RISING: + ret = regmap_read(st->regmap, + adxl345_act_thresh_reg[ADXL345_ACTIVITY], + &act_threshold); + if (ret) + return ret; + + *val = act_threshold; + return IIO_VAL_INT; + default: + return -EINVAL; + } + default: + return -EINVAL; + } case IIO_EV_TYPE_GESTURE: switch (info) { case IIO_EV_INFO_VALUE: @@ -835,6 +991,25 @@ static int adxl345_write_event_value(struct iio_dev *indio_dev, return ret; switch (type) { + case IIO_EV_TYPE_THRESH: + switch (info) { + case IIO_EV_INFO_VALUE: + switch (dir) { + case IIO_EV_DIR_RISING: + ret = regmap_write(st->regmap, + adxl345_act_thresh_reg[ADXL345_ACTIVITY], + val); + if (ret) + return ret; + break; + default: + return -EINVAL; + } + break; + default: + return -EINVAL; + } + break; case IIO_EV_TYPE_GESTURE: switch (info) { case IIO_EV_INFO_VALUE: @@ -1093,7 +1268,8 @@ static int adxl345_fifo_push(struct iio_dev *indio_dev, } 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 = iio_get_time_ns(indio_dev); struct adxl345_state *st = iio_priv(indio_dev); @@ -1120,6 +1296,16 @@ static int adxl345_push_event(struct iio_dev *indio_dev, int int_stat, return ret; } + if (FIELD_GET(ADXL345_INT_ACTIVITY, int_stat)) { + ret = iio_push_event(indio_dev, + IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, act_dir, + IIO_EV_TYPE_THRESH, + IIO_EV_DIR_RISING), + ts); + if (ret) + return ret; + } + if (FIELD_GET(ADXL345_INT_FREE_FALL, int_stat)) { ret = iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, @@ -1158,6 +1344,7 @@ static irqreturn_t adxl345_irq_handler(int irq, void *p) struct adxl345_state *st = iio_priv(indio_dev); unsigned int regval; enum iio_modifier tap_dir = IIO_NO_MOD; + enum iio_modifier act_dir = IIO_NO_MOD; u32 axis_ctrl; int int_stat; int ret; @@ -1166,7 +1353,8 @@ static irqreturn_t adxl345_irq_handler(int irq, void *p) if (ret) return IRQ_NONE; - 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 = regmap_read(st->regmap, ADXL345_REG_ACT_TAP_STATUS, ®val); if (ret) return IRQ_NONE; @@ -1177,12 +1365,19 @@ static irqreturn_t adxl345_irq_handler(int irq, void *p) tap_dir = IIO_MOD_Y; else if (FIELD_GET(ADXL345_TAP_X_EN, regval)) tap_dir = IIO_MOD_X; + + if (FIELD_GET(ADXL345_ACT_Z_EN, regval)) + act_dir = IIO_MOD_Z; + else if (FIELD_GET(ADXL345_ACT_Y_EN, regval)) + act_dir = IIO_MOD_Y; + else if (FIELD_GET(ADXL345_ACT_X_EN, regval)) + act_dir = IIO_MOD_X; } if (regmap_read(st->regmap, ADXL345_REG_INT_SOURCE, &int_stat)) return IRQ_NONE; - if (adxl345_push_event(indio_dev, int_stat, tap_dir)) + if (adxl345_push_event(indio_dev, int_stat, tap_dir, act_dir)) goto err; if (FIELD_GET(ADXL345_INT_OVERRUN, int_stat)) @@ -1347,6 +1542,14 @@ int adxl345_core_probe(struct device *dev, struct regmap *regmap, if (ret) return ret; + ret = regmap_write(st->regmap, ADXL345_REG_ACT_INACT_CTRL, 0); + if (ret) + return ret; + + ret = regmap_write(st->regmap, ADXL345_REG_THRESH_ACT, 6); + if (ret) + return ret; + ret = regmap_write(st->regmap, ADXL345_REG_THRESH_TAP, tap_threshold); if (ret) return ret; From patchwork Tue Mar 18 23:08:41 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lothar Rubusch X-Patchwork-Id: 14021722 Received: from mail-wm1-f44.google.com (mail-wm1-f44.google.com [209.85.128.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 32CDE215076; Tue, 18 Mar 2025 23:09:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.44 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742339349; cv=none; b=KVpmu3dMsBEO1MsfsRyjC4FBzLcZaThxvQBy86mRSjpK4GqIjGAUkLf/LQcJ/Tu2EDV5moBMccP+lvoUCbNOcjjbriVFbG+8ZOkbJ9B5+IFTgKApbyPzQzFPGD0nhK4BYWQgjOV1bjxN03226mqZvBv6NFSLrVjDbJfkFU4zCiQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742339349; c=relaxed/simple; bh=xEXSbaibN3QHw05OQ3jieNg7GhHZ50nM21wzNuufd9Y=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=UbIXN58GnDGi9SdMHmoQKXBWo7jyqLOqt8RzssCyF7CUkaUBe5qbhPJx3ynZ4SfyN5Em9aGfV9zkFO40ja4lsNkvMbs5sN3LiL7I3P+u4uH+AEZSQ0okT0DrnH69qHMWkSGgUESXUGxq8YcVEDWQzXDkm6vewekuvuocaNqJ55I= 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=eCSf/Tha; arc=none smtp.client-ip=209.85.128.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="eCSf/Tha" Received: by mail-wm1-f44.google.com with SMTP id 5b1f17b1804b1-4394944f161so2760235e9.3; Tue, 18 Mar 2025 16:09:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1742339345; x=1742944145; 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=3b2TleVB8YJe7W3d0ZwwgheLtzRt6Of/5V2RlbJn1LU=; b=eCSf/Tha68DutJydkGFrJSCfYiAc99K83CyYUJ3TDzKkyTLSG7WP0JzN8GaxLu72Mx yKKHksXmwGCj+1AiXfz6491entNc9Ntv4Mo9amX/tVhWdk0pW5yrIoA4ZLPv2TujwSa1 XZVx2sFh1gqS4OJ7HS/45GQV7iMOp5PcdpSCWoZjTKYY1yVAhZebNxiC5sqerflp1vvR jYdw3YqIrrlCt1iMn7UOeWWkT2ljrYMlJHnLYCPJvxFoCgs4uzkCHRdtY7xy1MtbUFUt vbEXdGb7JRtxfR/6EEVJiwujjyqt7e1pEw5oECdv7q8yyYDm4IjEzFWCNvfl18o2KGc9 MF1g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1742339345; x=1742944145; 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=3b2TleVB8YJe7W3d0ZwwgheLtzRt6Of/5V2RlbJn1LU=; b=fK6434pdy/Q0EbmpnOfOU5qwdZ5QOTf1S2jYlBveiM4sF1EVr5KA6ZudHQb1C3K4Il 4OsAdvDtyKLS6OUJewRILF9cCAlk8akWHlxe2b+QbuTddLWi9ligFie+QFUCc5rWBLt3 j3D36aH1RDwXfsJ5gPk1FXxfl9bzz/0EPja42n5stRqVlX6OlOu8rQRs0DZJyZXyRdyi zbl6gj79/dpebac4RSEKNibtuZOlCsWALzjHPTKV9RMLzpi60gh64I8+Tx68BbxP9zpV WzuMr+DLq/YByvGwlpMi/ObGvpQftOAKmmcpOENfyeJ9M7qbKg5wa1MAIAzjYz+jZiK3 vyUQ== X-Forwarded-Encrypted: i=1; AJvYcCXUsl0eB7vZoYn8FZlVs2ePBNT7o6vaqn0OBLomsvbYjYth9mfxK5zzy8HS2+kED055PqKGgWZOTQtW5x0=@vger.kernel.org X-Gm-Message-State: AOJu0YwBi5Nj7zs7N1cpcMy4g9LgAiRXSirayYbQc/bZ1PtaTXsXL1ff WUH9dQ5aAB5bro4sKPoU+zhmVxH9JqRGI0yjn8k+GYN+iSR/OoE7 X-Gm-Gg: ASbGnctoZ1fxduEhLm0wpP1fNQOpD47v9N5OnMkE0YGAL0Dj2bBd1VgP7jQCb700tvB MuyUuIXZIZZiWJExYfMPbtZr1GoN7r5CFVm9aw+1BCfPSGDwuhWQuXht1URvuOPLFx10craYLot 4riFD5k289fVvZ2NK4hup1MkdwsRHyC1fZxUU0211rAxgcMbIRssKt8fuK3xUm0us0hRAJSebqz RGTkX/q+MQfpETH/xGUkAF41XG+9A0UtnZcqVOOpFW2U1fm3u9/BlPqKZs9E/rCPd/kLpT6nhBi q5ciyiI5H9frJ3SX+qqzo2ZsXg46IZFPLGrZI0ZZZxxGNpdCq+aeNECd4+Q6cw1I8x+4WT1zAFc Ro+779FztizwJ03sD3KJA8l8= X-Google-Smtp-Source: AGHT+IEy6MGSCV76H7WwE1/cUWxziCST5LTp66OKmlbIIXot6bi/KXK7ud2lY3grOKoL5MWPQROUkg== X-Received: by 2002:a05:600c:4fd3:b0:439:9595:c8f4 with SMTP id 5b1f17b1804b1-43d436c8539mr1221925e9.0.1742339345192; Tue, 18 Mar 2025 16:09:05 -0700 (PDT) Received: from 0e1b0684397b.v.cablecom.net (84-72-156-211.dclient.hispeed.ch. [84.72.156.211]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-43d440ed793sm1113455e9.39.2025.03.18.16.09.04 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 18 Mar 2025 16:09:04 -0700 (PDT) From: Lothar Rubusch To: lars@metafoo.de, Michael.Hennerich@analog.com, jic23@kernel.org Cc: linux-iio@vger.kernel.org, linux-kernel@vger.kernel.org, eraretuya@gmail.com, l.rubusch@gmail.com Subject: [PATCH v5 09/11] iio: accel: adxl345: add inactivity feature Date: Tue, 18 Mar 2025 23:08:41 +0000 Message-Id: <20250318230843.76068-10-l.rubusch@gmail.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250318230843.76068-1-l.rubusch@gmail.com> References: <20250318230843.76068-1-l.rubusch@gmail.com> Precedence: bulk X-Mailing-List: linux-iio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Add the inactivity feature of the sensor. When activity and inactivity are enabled, a link bit will be set linking activity and inactivity handling. Additionally, the auto-sleep mode will be enabled. Due to the link bit the sensor is going to auto-sleep when inactivity was detected. Inactivity detection needs a threshold to be configured, and a time after which it will go into inactivity state if measurements under threshold. When a ODR is configured this time for inactivity is adjusted with a corresponding reasonable default value, in order to have higher frequencies and lower inactivity times, and lower sample frequency but give more time until inactivity. Both with reasonable upper and lower boundaries, since many of the sensor's features (e.g. auto-sleep) will need to operate beween 12.5 Hz and 400 Hz. This is a default setting when actively changing sample frequency, explicitly setting the time until inactivity will overwrite the default. Similarly, setting the g-range will provide a default value for the activity and inactivity thresholds. Both are implicit defaults, but equally can be overwritten to be explicitly configured. Signed-off-by: Lothar Rubusch --- drivers/iio/accel/adxl345_core.c | 167 ++++++++++++++++++++++++++++++- 1 file changed, 163 insertions(+), 4 deletions(-) diff --git a/drivers/iio/accel/adxl345_core.c b/drivers/iio/accel/adxl345_core.c index 6b8491202119..3b841032d41b 100644 --- a/drivers/iio/accel/adxl345_core.c +++ b/drivers/iio/accel/adxl345_core.c @@ -37,11 +37,17 @@ #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 | ADXL345_POWER_CTL_LINK) #define ADXL345_TAP_Z_EN BIT(0) #define ADXL345_TAP_Y_EN BIT(1) #define ADXL345_TAP_X_EN BIT(2) +#define ADXL345_INACT_Z_EN BIT(0) +#define ADXL345_INACT_Y_EN BIT(1) +#define ADXL345_INACT_X_EN BIT(2) + #define ADXL345_ACT_Z_EN BIT(4) #define ADXL345_ACT_Y_EN BIT(5) #define ADXL345_ACT_X_EN BIT(6) @@ -72,14 +78,17 @@ static const unsigned int adxl345_tap_time_reg[] = { /* activity/inactivity */ enum adxl345_activity_type { ADXL345_ACTIVITY, + ADXL345_INACTIVITY, }; static const unsigned int adxl345_act_int_reg[] = { [ADXL345_ACTIVITY] = ADXL345_INT_ACTIVITY, + [ADXL345_INACTIVITY] = ADXL345_INT_INACTIVITY, }; static const unsigned int adxl345_act_thresh_reg[] = { [ADXL345_ACTIVITY] = ADXL345_REG_THRESH_ACT, + [ADXL345_INACTIVITY] = ADXL345_REG_THRESH_INACT, }; enum adxl345_odr { @@ -179,6 +188,14 @@ static struct iio_event_spec adxl345_events[] = { .mask_separate = BIT(IIO_EV_INFO_ENABLE), .mask_shared_by_type = BIT(IIO_EV_INFO_VALUE), }, + { + /* inactivity */ + .type = IIO_EV_TYPE_THRESH, + .dir = IIO_EV_DIR_FALLING, + .mask_separate = BIT(IIO_EV_INFO_ENABLE), + .mask_shared_by_type = BIT(IIO_EV_INFO_VALUE) | + BIT(IIO_EV_INFO_PERIOD), + }, { /* single tap */ .type = IIO_EV_TYPE_GESTURE, @@ -310,6 +327,20 @@ static int adxl345_is_act_inact_en(struct adxl345_state *st, default: return -EINVAL; } + } else { + switch (axis) { + case IIO_MOD_X: + axis_en = FIELD_GET(ADXL345_INACT_X_EN, axis_ctrl); + break; + case IIO_MOD_Y: + axis_en = FIELD_GET(ADXL345_INACT_Y_EN, axis_ctrl); + break; + case IIO_MOD_Z: + axis_en = FIELD_GET(ADXL345_INACT_Z_EN, axis_ctrl); + break; + default: + return -EINVAL; + } } ret = regmap_read(st->regmap, ADXL345_REG_INT_ENABLE, ®val); @@ -327,6 +358,7 @@ static int adxl345_set_act_inact_en(struct adxl345_state *st, bool cmd_en) { bool axis_en, en; + unsigned int inact_time_s; unsigned int threshold; u32 axis_ctrl = 0; int ret; @@ -345,6 +377,20 @@ static int adxl345_set_act_inact_en(struct adxl345_state *st, default: return -EINVAL; } + } else { + switch (axis) { + case IIO_MOD_X: + axis_ctrl = ADXL345_INACT_X_EN; + break; + case IIO_MOD_Y: + axis_ctrl = ADXL345_INACT_Y_EN; + break; + case IIO_MOD_Z: + axis_ctrl = ADXL345_INACT_Z_EN; + break; + default: + return -EINVAL; + } } if (cmd_en) @@ -365,11 +411,67 @@ static int adxl345_set_act_inact_en(struct adxl345_state *st, if (type == ADXL345_ACTIVITY) { axis_en = FIELD_GET(ADXL345_REG_ACT_AXIS_MSK, axis_ctrl) > 0; en = axis_en && threshold > 0; + } else { + ret = regmap_read(st->regmap, ADXL345_REG_TIME_INACT, &inact_time_s); + if (ret) + return ret; + + axis_en = FIELD_GET(ADXL345_REG_INACT_AXIS_MSK, axis_ctrl) > 0; + en = axis_en && threshold > 0 && inact_time_s > 0; } - return regmap_update_bits(st->regmap, ADXL345_REG_INT_ENABLE, - adxl345_act_int_reg[type], - en ? adxl345_act_int_reg[type] : 0); + ret = regmap_update_bits(st->regmap, ADXL345_REG_INT_ENABLE, + adxl345_act_int_reg[type], + en ? adxl345_act_int_reg[type] : 0); + if (ret) + return ret; + + return regmap_update_bits(st->regmap, ADXL345_REG_POWER_CTL, + ADXL345_POWER_CTL_INACT_MSK, + en ? (ADXL345_POWER_CTL_AUTO_SLEEP | ADXL345_POWER_CTL_LINK) + : 0); +} + +/** + * adxl345_set_inact_time_s - Configure inactivity time explicitly or by ODR. + * @st: The sensor state instance. + * @val_s: A desired time value, between 0 and 255. + * + * If val_s is 0, a default inactivity time will be computed. It should take + * power consumption into consideration. Thus it shall be shorter for higher + * frequencies and longer for lower frequencies. Hence, frequencies above 255 Hz + * shall default to 10 s and frequencies below 10 Hz shall result in 255 s to + * detect inactivity. + * + * The approach simply subtracts the pre-decimal figure of the configured + * sample frequency from 255 s to compute inactivity time [s]. Sub-Hz are thus + * ignored in this estimation. The recommended ODRs for various features + * (activity/inactivity, sleep modes, free fall, etc.) lie between 12.5 Hz and + * 400 Hz, thus higher or lower frequencies will result in the boundary + * defaults or need to be explicitly specified via val_s. + * + * Return: 0 or error value. + */ +static int adxl345_set_inact_time_s(struct adxl345_state *st, u32 val_s) +{ + unsigned int max_boundary = 255; + unsigned int min_boundary = 10; + unsigned int val = min(val_s, max_boundary); + enum adxl345_odr odr; + unsigned int regval; + int ret; + + if (val == 0) { + ret = regmap_read(st->regmap, ADXL345_REG_BW_RATE, ®val); + if (ret) + return ret; + odr = FIELD_GET(ADXL345_BW_RATE_MSK, regval); + + val = (adxl345_odr_tbl[odr][0] > max_boundary) + ? min_boundary : max_boundary - adxl345_odr_tbl[odr][0]; + } + + return regmap_write(st->regmap, ADXL345_REG_TIME_INACT, val); } /* tap */ @@ -829,6 +931,13 @@ static int adxl345_read_event_config(struct iio_dev *indio_dev, if (ret) return ret; return int_en; + case IIO_EV_DIR_FALLING: + ret = adxl345_is_act_inact_en(st, chan->channel2, + ADXL345_INACTIVITY, + &int_en); + if (ret) + return ret; + return int_en; default: return -EINVAL; } @@ -873,6 +982,9 @@ static int adxl345_write_event_config(struct iio_dev *indio_dev, case IIO_EV_DIR_RISING: return adxl345_set_act_inact_en(st, chan->channel2, ADXL345_ACTIVITY, state); + case IIO_EV_DIR_FALLING: + return adxl345_set_act_inact_en(st, chan->channel2, + ADXL345_INACTIVITY, state); default: return -EINVAL; } @@ -900,7 +1012,8 @@ static int adxl345_read_event_value(struct iio_dev *indio_dev, int *val, int *val2) { struct adxl345_state *st = iio_priv(indio_dev); - unsigned int act_threshold; + unsigned int act_threshold, inact_threshold; + unsigned int inact_time_s; unsigned int tap_threshold; unsigned int ff_threshold; int ret; @@ -919,9 +1032,24 @@ static int adxl345_read_event_value(struct iio_dev *indio_dev, *val = act_threshold; return IIO_VAL_INT; + case IIO_EV_DIR_FALLING: + ret = regmap_read(st->regmap, + adxl345_act_thresh_reg[ADXL345_INACTIVITY], + &inact_threshold); + if (ret) + return ret; + + *val = inact_threshold; + return IIO_VAL_INT; default: return -EINVAL; } + case IIO_EV_INFO_PERIOD: + ret = regmap_read(st->regmap, ADXL345_REG_TIME_INACT, &inact_time_s); + if (ret) + return ret; + *val = inact_time_s; + return IIO_VAL_INT; default: return -EINVAL; } @@ -1002,10 +1130,22 @@ static int adxl345_write_event_value(struct iio_dev *indio_dev, if (ret) return ret; break; + case IIO_EV_DIR_FALLING: + ret = regmap_write(st->regmap, + adxl345_act_thresh_reg[ADXL345_INACTIVITY], + val); + if (ret) + return ret; + break; default: return -EINVAL; } break; + case IIO_EV_INFO_PERIOD: + ret = adxl345_set_inact_time_s(st, val); + if (ret) + return ret; + break; default: return -EINVAL; } @@ -1306,6 +1446,17 @@ static int adxl345_push_event(struct iio_dev *indio_dev, int int_stat, return ret; } + if (FIELD_GET(ADXL345_INT_INACTIVITY, int_stat)) { + ret = iio_push_event(indio_dev, + IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, + IIO_MOD_X_OR_Y_OR_Z, + IIO_EV_TYPE_THRESH, + IIO_EV_DIR_FALLING), + ts); + if (ret) + return ret; + } + if (FIELD_GET(ADXL345_INT_FREE_FALL, int_stat)) { ret = iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, @@ -1546,10 +1697,18 @@ int adxl345_core_probe(struct device *dev, struct regmap *regmap, if (ret) return ret; + ret = regmap_write(st->regmap, ADXL345_REG_TIME_INACT, 3); + if (ret) + return ret; + ret = regmap_write(st->regmap, ADXL345_REG_THRESH_ACT, 6); if (ret) return ret; + ret = regmap_write(st->regmap, ADXL345_REG_THRESH_INACT, 4); + if (ret) + return ret; + ret = regmap_write(st->regmap, ADXL345_REG_THRESH_TAP, tap_threshold); if (ret) return ret; From patchwork Tue Mar 18 23:08:42 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lothar Rubusch X-Patchwork-Id: 14021723 Received: from mail-wr1-f50.google.com (mail-wr1-f50.google.com [209.85.221.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 49BC22153C4; Tue, 18 Mar 2025 23:09:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.50 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742339350; cv=none; b=Gg8nCfWtu9A4q1PRT0CtVvn4wrM6eKLYXk6zgCT2jcDG7qfMA2MTNOs3shmV5x0Hk9RLtH8gTk7e4oh42FRaJNHWIVar4/gWtClusSU6FD4dn5Yp+oGXU6wjEh9MhqFWtiWQypWbxjilBXz4mLjHHZMGgzSujhq9LfVQOGiJvoQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742339350; c=relaxed/simple; bh=kh+x+b4Qv5K6soJVwQuWos+FYwV/Inyyy52QBlUrV0w=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=EFIMCzQwwxg2KutFAsvE5PNETJfi5ehHrlDOnEmmRI5UIubMwcrmjSKWFIzofPYD2xfj8v5wnNT1NGDD3OEGAS0vm/QOmMws4QfGTKayiWTiuGdoQfWTITvn3Lv1oRn6NwrIfn22si4d1xR6SFP4oD63X80r+JOzkd0sLunn6Ic= 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=Dl1YV63v; arc=none smtp.client-ip=209.85.221.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="Dl1YV63v" Received: by mail-wr1-f50.google.com with SMTP id ffacd0b85a97d-3996683dd7bso392991f8f.3; Tue, 18 Mar 2025 16:09:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1742339346; x=1742944146; 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=Wq/EAL+TvIEsau/5MxNqALDLxnYs3DXhVk3Fq5Cp8SU=; b=Dl1YV63vjW7jfx+MFBfuQNHPiBsXqCJmxaAHxNNrKvhH4ES8hq0sRVf6FTLcn98eTO 96RJWXWkN5A3syDJ55z2B3dTFTOKZbpX5TtIumEB90tDCLFdtWj65khqySfAJWGm60UG VYIMgMn7kvrugy/A9Lz31pyniYfKjeAsUqGbWgGyfD7r7PxLD0xpdxWaYVhsP3+b4sHh VtFBJx5c43qh0QEm954VLhCoAN2LPCzFCRVQVJUlBVIHlJ3p1eggiC2eqXbJ/kTu+kR/ dvC52KzSz4OeM7QLMqt57c7JSnOcLE/sAL2rbTXwAX1V7HDAoBW582oAJrG6Mr1gSSSI FpDQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1742339346; x=1742944146; 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=Wq/EAL+TvIEsau/5MxNqALDLxnYs3DXhVk3Fq5Cp8SU=; b=P2tIdobr9KvUQ+zYZ7eRegtlk2sQJ+UM1Jsk7HGfvAHL9/MnhI4TZD3LPL45RU1HGM Q1M0ux05Tm7APBP80yMRmSSZrKgAzZJ8sGvw5pWpEUVQB0U/N6JxJhcFuaDe7Yrs4s2N cs0z3KYGVS0uB5dqVqJ5k9LN6KGc3YDQRx/ISzO8Ocho3RZ1ZxJXnfcqBTX40HdjQMZB 5Pr6XBLuecYYSC/WJvn2UQ/3YiX6ZyEgocZ0b2s7P+pl7wKne7J0qGbDFZgHce77bxOn mQEAX11su9HQvJdPamV1L6Z7WVXjS6v3Lh65AxLkMBOv54O8VWDa7zarzB1HufUHehJ1 ziHw== X-Forwarded-Encrypted: i=1; AJvYcCW4E5ydXz+cwnRhqNttp8QjZNjEtvQFx5lCc6rLTbPUh0gJMjuXJj5RQNsbtLBtDwPujV8l7sTC7TLOF8o=@vger.kernel.org X-Gm-Message-State: AOJu0Yz/K2m/0ON8URREFZHicAZptya7AHPNvdUTbs9BHIXO8J3BzxgM kOZKmO/eKz2Az+W3U+NiTRZaROWOAbmbVZNpTmgLHdqsDU7aaVXS X-Gm-Gg: ASbGnctC4sh2CPbGPYedRyLJcuJfXVcmEId3PkzxodsxGMMDB/ZBi5OV11cwh7FIaAC ob/CH2AlYUQKihHggBZQOsEOQY0vIsOXqF8YILYD77bS2MpX3mzuJ4RHab2hB9UZ+fw65YabI4l jA9kCp2roJLXUtauqu1Z5/V+PQAfROmHj3vBAZudYAAsmHaoh+5JDldLvn+owqVleeg5Ti0s8PO L6D++1kWAijhhqE0PQSbDuZE0iaHcJF7zL+g0mAAIClTR1TqzuvWq0eu8GY2XMjEnDru083bukE wjPF6pG8JwE937pzIsKTiADsE8VrSbAX+UbuJwtSWKwy6Xu8OnZPqG3zXKO5rNC7otuJcJhHfV5 bj3fi9h6jgWGrZ3Af/5Hyk8w= X-Google-Smtp-Source: AGHT+IEzO75XNfp84qPlu5sKKlmRvEj95fvaIR2YRpLGHNV33HoUqtebs+xbZ6trKfjpGAh7qqhVYA== X-Received: by 2002:a05:6000:1f8e:b0:391:1319:9007 with SMTP id ffacd0b85a97d-399739e1bc6mr211654f8f.5.1742339346386; Tue, 18 Mar 2025 16:09:06 -0700 (PDT) Received: from 0e1b0684397b.v.cablecom.net (84-72-156-211.dclient.hispeed.ch. [84.72.156.211]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-43d440ed793sm1113455e9.39.2025.03.18.16.09.05 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 18 Mar 2025 16:09:05 -0700 (PDT) From: Lothar Rubusch To: lars@metafoo.de, Michael.Hennerich@analog.com, jic23@kernel.org Cc: linux-iio@vger.kernel.org, linux-kernel@vger.kernel.org, eraretuya@gmail.com, l.rubusch@gmail.com Subject: [PATCH v5 10/11] iio: accel: adxl345: add coupling detection for activity/inactivity Date: Tue, 18 Mar 2025 23:08:42 +0000 Message-Id: <20250318230843.76068-11-l.rubusch@gmail.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250318230843.76068-1-l.rubusch@gmail.com> References: <20250318230843.76068-1-l.rubusch@gmail.com> Precedence: bulk X-Mailing-List: linux-iio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Add coupling activity/inactivity detection by the AC/DC bit. This is an addititional enhancement for the detection of activity states and completes the activity / inactivity feature of the ADXL345. Signed-off-by: Lothar Rubusch --- drivers/iio/accel/adxl345_core.c | 162 ++++++++++++++++++++++++++++++- 1 file changed, 160 insertions(+), 2 deletions(-) diff --git a/drivers/iio/accel/adxl345_core.c b/drivers/iio/accel/adxl345_core.c index 3b841032d41b..35bed998083b 100644 --- a/drivers/iio/accel/adxl345_core.c +++ b/drivers/iio/accel/adxl345_core.c @@ -37,7 +37,9 @@ #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_ACT_ACDC_MSK BIT(7) #define ADXL345_REG_INACT_AXIS_MSK GENMASK(2, 0) +#define ADXL345_REG_INACT_ACDC_MSK BIT(3) #define ADXL345_POWER_CTL_INACT_MSK (ADXL345_POWER_CTL_AUTO_SLEEP | ADXL345_POWER_CTL_LINK) #define ADXL345_TAP_Z_EN BIT(0) @@ -91,6 +93,11 @@ static const unsigned int adxl345_act_thresh_reg[] = { [ADXL345_INACTIVITY] = ADXL345_REG_THRESH_INACT, }; +static const unsigned int adxl345_act_acdc_msk[] = { + [ADXL345_ACTIVITY] = ADXL345_REG_ACT_ACDC_MSK, + [ADXL345_INACTIVITY] = ADXL345_REG_INACT_ACDC_MSK, +}; + enum adxl345_odr { ADXL345_ODR_0P10HZ = 0, ADXL345_ODR_0P20HZ, @@ -220,6 +227,18 @@ static struct iio_event_spec adxl345_events[] = { BIT(IIO_EV_INFO_VALUE) | BIT(IIO_EV_INFO_PERIOD), }, + { + /* activity, activity - ac bit */ + .type = IIO_EV_TYPE_MAG_REFERENCED, + .dir = IIO_EV_DIR_RISING, + .mask_shared_by_type = BIT(IIO_EV_INFO_ENABLE), + }, + { + /* activity, inactivity - ac bit */ + .type = IIO_EV_TYPE_MAG_REFERENCED, + .dir = IIO_EV_DIR_FALLING, + .mask_shared_by_type = BIT(IIO_EV_INFO_ENABLE), + }, }; #define ADXL345_CHANNEL(index, reg, axis) { \ @@ -300,6 +319,69 @@ static int adxl345_set_measure_en(struct adxl345_state *st, bool en) /* act/inact */ +static int adxl345_is_act_inact_ac(struct adxl345_state *st, + enum adxl345_activity_type type, bool *ac) +{ + unsigned int regval; + int ret; + + ret = regmap_read(st->regmap, ADXL345_REG_ACT_INACT_CTRL, ®val); + if (ret) + return ret; + + if (type == ADXL345_ACTIVITY) + *ac = (FIELD_GET(ADXL345_REG_ACT_ACDC_MSK, regval) > 0); + else + *ac = (FIELD_GET(ADXL345_REG_INACT_ACDC_MSK, regval) > 0); + + return 0; +} + +static int adxl345_set_act_inact_ac(struct adxl345_state *st, + enum adxl345_activity_type type, bool ac) +{ + unsigned int act_inact_ac = ac ? 0xff : 0x00; + + /* + * 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_update_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 iio_modifier axis, enum adxl345_activity_type type, bool *en) @@ -754,9 +836,16 @@ static int adxl345_find_odr(struct adxl345_state *st, int val, 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 = 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_s(st, 0); } static int adxl345_find_range(struct adxl345_state *st, int val, int val2, @@ -777,9 +866,51 @@ static int adxl345_find_range(struct adxl345_state *st, int val, int val2, 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 = regmap_read(st->regmap, ADXL345_REG_DATA_FORMAT, ®val); + if (ret) + return ret; + range_old = FIELD_GET(ADXL345_DATA_FORMAT_RANGE, regval); + + ret = regmap_read(st->regmap, + adxl345_act_thresh_reg[ADXL345_ACTIVITY], + &act_threshold); + if (ret) + return ret; + + ret = regmap_read(st->regmap, + adxl345_act_thresh_reg[ADXL345_INACTIVITY], + &inact_threshold); + if (ret) + return ret; + + ret = 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 = act_threshold + * adxl345_range_factor_tbl[range_old] + / adxl345_range_factor_tbl[range]; + act_threshold = min(255, max(1, inact_threshold)); + + inact_threshold = inact_threshold + * adxl345_range_factor_tbl[range_old] + / adxl345_range_factor_tbl[range]; + inact_threshold = min(255, max(1, inact_threshold)); + + ret = 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); } static int adxl345_read_avail(struct iio_dev *indio_dev, @@ -919,6 +1050,8 @@ static int adxl345_read_event_config(struct iio_dev *indio_dev, { struct adxl345_state *st = iio_priv(indio_dev); bool int_en; + bool act_ac; + bool inact_ac; int ret; switch (type) { @@ -963,6 +1096,21 @@ static int adxl345_read_event_config(struct iio_dev *indio_dev, if (ret) return ret; return int_en; + case IIO_EV_TYPE_MAG_REFERENCED: + switch (dir) { + case IIO_EV_DIR_RISING: + ret = adxl345_is_act_inact_ac(st, ADXL345_ACTIVITY, &act_ac); + if (ret) + return ret; + return act_ac; + case IIO_EV_DIR_FALLING: + ret = adxl345_is_act_inact_ac(st, ADXL345_INACTIVITY, &inact_ac); + if (ret) + return ret; + return inact_ac; + default: + return -EINVAL; + } default: return -EINVAL; } @@ -999,6 +1147,16 @@ static int adxl345_write_event_config(struct iio_dev *indio_dev, } case IIO_EV_TYPE_MAG: return adxl345_set_ff_en(st, state); + case IIO_EV_TYPE_MAG_REFERENCED: + switch (dir) { + case IIO_EV_DIR_RISING: + return adxl345_set_act_inact_ac(st, ADXL345_ACTIVITY, state); + case IIO_EV_DIR_FALLING: + return adxl345_set_act_inact_ac(st, ADXL345_INACTIVITY, state); + default: + return -EINVAL; + } + default: return -EINVAL; } From patchwork Tue Mar 18 23:08:43 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Lothar Rubusch X-Patchwork-Id: 14021724 Received: from mail-wr1-f45.google.com (mail-wr1-f45.google.com [209.85.221.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 B868D217647; Tue, 18 Mar 2025 23:09:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.45 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742339352; cv=none; b=JiEYBtnfmLPP6urlS9Y8TEv50nsbAhmt4KUJMsshMJce7epR3W6FjaqViO9OtkU7D+ze3f4vrfkiw3PYS46Hhos+CAHgxMxY+Fs120oXyUP6aHs2N6TaMYNtNG/jwU41s1DrzNgqHinu/3mrOwUIVXfaFlDzruaTxU1t5Nnt5vA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742339352; c=relaxed/simple; bh=J+gxOK9BmXWp+MSs2VJ9oOXAZgisi21PoNI0mvLG0p4=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version:Content-Type; b=XhNrIqYAiX6M2g9hDbO9WeN7O0FT5UIIcBE9rR1YqKYQSJrhb9W7000Ph9GWFmdfrfRsX2ToLHAFs1Ky5c8HJuH+FutIndx9GdGt+Q7VvqOz6dN8f9O45UBemaBuKzMY7mGDGpjbgnIa6THFuxyQ3wK4Fv7nQMcH9BTz3fYnvH8= 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=mu9hrKU0; arc=none smtp.client-ip=209.85.221.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="mu9hrKU0" Received: by mail-wr1-f45.google.com with SMTP id ffacd0b85a97d-3912622c9c0so974611f8f.3; Tue, 18 Mar 2025 16:09:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1742339348; x=1742944148; 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=v27Lnlqr3GEvQfW7w8hZ2MQ04yP2vRncP9MW1QBJDBo=; b=mu9hrKU043hBbDKsyeNZju7gHGCJDtFj69zHwQhA1Gr0HQIqSLAor8JxW+mitTjoGA qXEaCq0GLWNlauEXOTtOzR6Q9dJmprYRm/eTHH6qQVnUZ35Z0pxAgZUJSzjqWGa/BZmw +2fr3EYboQ4N9KlDbUNxS51XWqH1mJAZhi23wI0VQ4T5MMFbH2lPcRz2aN1+GdZS/zNt +ld9OYBt3CKhBB72vMXBIgNYiKOhBTEswSd02bStqxxxOrr09FX0RQvZ4ZmjJSKgmKLt Rz5dvSs+xK8YdlQ2067kqSH/AeDV8A2i/hQneuKAksBvBvleUtDXxFIxoiabC3nEKGvp 8Ceg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1742339348; x=1742944148; 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=v27Lnlqr3GEvQfW7w8hZ2MQ04yP2vRncP9MW1QBJDBo=; b=kJWDmDYgtUEZ48Fspbl00uselwE6IQXBuvWtEJifrn/NWTZWqeBOOM2bl6RWGg9BTm DazY8QZBUp1NICk1WjPthOtNZ19Y713K9yTa2S+DSCsccIMO3IRiA5jDNz+Ld793iNN7 mMPL5SpHNBPg+tV0+TY3DgIjn2jW9kwjnhF/7+PYfe34/KTOE2b9hRYEjpG8hmWmPA9a wu8uMVfKvVw4xhUx8b4uR4xIpFDNMn8od2bRkSRIMNe5do4qZ/v6A2VAyijhTdSGgomC eZ5jx5Lp+/HM4hWtE5mCzIw2ayQQCNHggfcDmlXWaOkY7utJDXdSkbGlzZY8NJ/z5BEr MO7Q== X-Forwarded-Encrypted: i=1; AJvYcCXd8Km+NaXAD1k1refxZNGsGxM1T42e6HLpjcKbb2CPWexQo0n0Bs4usFqa+h5Lzawnaj40t7OJ9O+IL78=@vger.kernel.org X-Gm-Message-State: AOJu0Yy1onkO4JtFki3SFQ3+v1AVpfBTvctV4y8oeY+EYF+IwnYkGMV+ JLoP5zLxch2PuFxqfNb+TiU4sasKN+QMD+Kja0D8e43QHVOsGS2E X-Gm-Gg: ASbGncuy9++UKh5EeOxzHaXzWS0X2VpOvEhT6dXARtjXkKmglRjCONY0QFASoe9Pzf6 KE7zHXdlk313tpXREU+AJyAmiYlLfOg7uDD3gNnm2VdYv82ZFuuHkK0KHPzAPEKOLBFw33HRwSG Wimn7uRPACi91siFRAUUFtIVbkSrfMyYD8qZ/H4mpFjerhT/SLFSGJRWocHTmYV/8azLBDx57NN tveKW+a2lIVFyudUxiWogQypzyqWBE31NyWWr5oe7jwSSNRLWmAe9xGhIpjmQROjsRPk8pbYI3g YadKH+tXs/6B0h803UcCHd/lkqSldiSsgMtJkn+WEqtrhObuU+yZZvWvkNZHeJfzvwnNlbRySrD 7LwWEvhBC/riNRwSflA1NPek= X-Google-Smtp-Source: AGHT+IGTtMtxOyij+GGKSngUqHx9Rsujxs1eXlbYqiBISFC7AJYW2SM+68JLvrRt9XcxuXh9gbLAoQ== X-Received: by 2002:a05:600c:3503:b0:43d:2318:ed7f with SMTP id 5b1f17b1804b1-43d436c8322mr1186375e9.0.1742339347702; Tue, 18 Mar 2025 16:09:07 -0700 (PDT) Received: from 0e1b0684397b.v.cablecom.net (84-72-156-211.dclient.hispeed.ch. [84.72.156.211]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-43d440ed793sm1113455e9.39.2025.03.18.16.09.06 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 18 Mar 2025 16:09:07 -0700 (PDT) From: Lothar Rubusch To: lars@metafoo.de, Michael.Hennerich@analog.com, jic23@kernel.org Cc: linux-iio@vger.kernel.org, linux-kernel@vger.kernel.org, eraretuya@gmail.com, l.rubusch@gmail.com Subject: [PATCH v5 11/11] docs: iio: add documentation for adxl345 driver Date: Tue, 18 Mar 2025 23:08:43 +0000 Message-Id: <20250318230843.76068-12-l.rubusch@gmail.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250318230843.76068-1-l.rubusch@gmail.com> References: <20250318230843.76068-1-l.rubusch@gmail.com> Precedence: bulk X-Mailing-List: linux-iio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 The documentation describes the ADXL345 driver, IIO interface, interface usage and configuration. Signed-off-by: Lothar Rubusch --- Documentation/iio/adxl345.rst | 416 ++++++++++++++++++++++++++++++++++ 1 file changed, 416 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..683121c1a435 --- /dev/null +++ b/Documentation/iio/adxl345.rst @@ -0,0 +1,416 @@ +.. SPDX-License-Identifier: GPL-2.0 + +=============== +ADXL345 driver +=============== + +This driver supports Analog Device's ADXL345/375 on SPI/I2C bus. + +1. Supported devices +==================== + +* `ADXL345 `_ +* `ADXL375 `_ + +The ADXL345 is a generic purpose low power, 3-axis accelerometer with selectable +measurement ranges. The ADXL345 supports the ±2 g, ±4 g, ±8 g, and ±16 g ranges. + +2. Device attributes +==================== + +Each IIO device, has a device folder under ``/sys/bus/iio/devices/iio:deviceX``, +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 documented 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 rate. | ++-------------------------------------------+----------------------------------------------------------+ +| in_accel_sampling_frequency_available | Available sampling frequency configurations. | ++-------------------------------------------+----------------------------------------------------------+ +| in_accel_scale | Scale/range for the accelerometer channels. | ++-------------------------------------------+----------------------------------------------------------+ +| in_accel_scale_available | Available scale ranges for the accelerometer channel. | ++-------------------------------------------+----------------------------------------------------------+ +| in_accel_x_calibbias | Calibration offset for the X-axis accelerometer channel. | ++-------------------------------------------+----------------------------------------------------------+ +| in_accel_x_raw | Raw X-axis accelerometer channel value. | ++-------------------------------------------+----------------------------------------------------------+ +| in_accel_y_calibbias | y-axis acceleration offset correction | ++-------------------------------------------+----------------------------------------------------------+ +| in_accel_y_raw | Raw Y-axis accelerometer channel value. | ++-------------------------------------------+----------------------------------------------------------+ +| in_accel_z_calibbias | Calibration offset for the Z-axis accelerometer channel. | ++-------------------------------------------+----------------------------------------------------------+ +| in_accel_z_raw | Raw Z-axis accelerometer channel 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 channel, +apply the following formula: + +.. code-block:: bash + + processed value = (_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 +------------- + +Particular IIO events will be triggered by the corresponding interrupts. The +sensor driver supports no or one active INT line, where the sensor has two +possible INT IOs. Configure the used INT line in the devicetree. If no INT line +is configured, the sensor falls back to FIFO bypass mode and no events are +possible, only X, Y and Z axis measurements are possible. + +The following table shows the ADXL345 related device files, found in the +specific device folder path ``/sys/bus/iio/devices/iio:deviceX/events``. + ++---------------------------------------------+-----------------------------------------+ +| Event handle | Description | ++---------------------------------------------+-----------------------------------------+ +| in_accel_gesture_doubletap_en | Enable double tap detection 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_en | Enable free fall detection | ++---------------------------------------------+-----------------------------------------+ +| in_accel_mag_falling_period | Free fall time in [us] | ++---------------------------------------------+-----------------------------------------+ +| in_accel_mag_falling_value | Free fall threshold value in 62.5/LSB | ++---------------------------------------------+-----------------------------------------+ +| in_accel_mag_referenced_falling_en | Set 1 to AC-coupled inactivity, 0 for DC| ++---------------------------------------------+-----------------------------------------+ +| in_accel_mag_referenced_rising_en | Set 1 to AC-coupled activity, 0 for DC | ++---------------------------------------------+-----------------------------------------+ +| in_accel_x_thresh_falling_en | Enable inactivity detection on X axis | ++---------------------------------------------+-----------------------------------------+ +| in_accel_y_thresh_falling_en | Enable inactivity detection on Y axis | ++---------------------------------------------+-----------------------------------------+ +| in_accel_z_thresh_falling_en | Enable inactivity detection on Z axis | ++---------------------------------------------+-----------------------------------------+ +| in_accel_thresh_falling_period | Inactivity time in seconds | ++---------------------------------------------+-----------------------------------------+ +| in_accel_thresh_falling_value | Inactivity threshold value in 62.5/LSB | ++---------------------------------------------+-----------------------------------------+ +| in_accel_x_thresh_rising_en | Enable activity detection on X axis | ++---------------------------------------------+-----------------------------------------+ +| in_accel_y_thresh_rising_en | Enable activity detection on Y axis | ++---------------------------------------------+-----------------------------------------+ +| in_accel_z_thresh_rising_en | Enable activity detection on Z axis | ++---------------------------------------------+-----------------------------------------+ +| in_accel_thresh_rising_value | Activity threshold value in 62.5/LSB | ++---------------------------------------------+-----------------------------------------+ +| in_accel_x_gesture_singletap_en | Enable single tap detection on X axis | ++---------------------------------------------+-----------------------------------------+ +| in_accel_y_gesture_singletap_en | Enable single tap detection on Y axis | ++---------------------------------------------+-----------------------------------------+ +| in_accel_z_gesture_singletap_en | Enable single tap detection on Z axis | ++---------------------------------------------+-----------------------------------------+ + +Find a detailed description of a particular functionality in the sensor +datasheet. + +Setting the ODR explicitly will result in estimated adjusted default values +for the inactivity time detection, where higher frequencies shall default to +longer wait periods, and vice versa. It is also possible to explicetly +configure inactivity wait times, if the defaulting approach does not match +application requirements. Setting 0 here, will fall back to default setting. + +The g range configuration also tries to estimate activity and inactivity +thresholds when switching to another g range. The default range will be +factorized by the relation of old range divided by new range. The value never +becomes 0 and will be at least 1 and at most 255 i.e. 62.5g/LSB according to +the datasheet. Nevertheless activity and inactivity thresholds can be +overwritten by explicit values. + +When activity and inactivity events are both enabled, the driver automatically +will implement its hysteresis solution by setting link bit and autosleep bit. +The link bit serially links the activity and inactivity functions. On the other +side, the autosleep function switches the sensor to sleep mode if the +inactivity function is enabled. This will reduce current consumption to the +sub-12.5Hz rate. + +In dc-coupled operation, the current acceleration magnitude is compared +directly with THRESH_ACT and THRESH_INACT registers to determine whether +activity or inactivity was 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 are then compared to this reference value. +Note, ac-coupling and dc-coupling are individually set for activity and/or +inactivity detection. Activity and inactivity detection are dependent on the +direction, i.e. the x/y/z axis where this driver generally enables all +directions. Also, the direction settings are particular to activity and +inactivity detection, respectively. + +Single tap detection can be configured according to the datasheet by specifying +threshold and duration. If only the single tap is in use, the single tap +interrupt is triggered when the acceleration goes above threshold (i.e. DUR +start) and below the threshold, as long as duration is not exceeded. If single +tap and double tap are in use, the single tap is triggered when the doulbe tap +event has been either validated or invalidated. + +For double tap configure additionally window and latency in [us]. Latency +starts counting when the single tap goes below threshold and is a waiting +period, any spikes here are ignored for double tap detection. After latency, +the window starts. Any rise above threshold, with a consequent fall below +threshold within window time, rises a double tap signal when going below +threshold. + +Double tap event detection is best described in the datasheet. After a +single tap event was detected, a double tap event can be detected. Therefore the +signal must match several criteria, and detection can also considered invalid +for three reasons: +* If the suppress bit is set and when still in the tap latency period, any +measurement of acceleration spike above the tap threshold invalidates double tap +detection immediately, i.e. during latency must not occur spikes for double tap +detection when the suppress bit is set. +* A double tap event is considered invalid, if acceleration lies above the +threshold at the start of the window time for double tap. +* Additionally, double tap detection can be considered invalid, if an +acceleration exceeds the time limit for taps, set by duration register. +Note, since for double tap the same duration counts, i.e. when rising above +threshold, a consequent falling below threshold has to be within duration time. +Also note, the suppress bit is generally set when double tap is enabled. + +A free fall event will be detected if the signal goes below the configured +threshold, for the configured time [us]. + +Note, that activity/inactivy, as also freefall is recommended for 12.5 Hz ODR +up to 400 Hz. + +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_calibbias + 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 the +following forumla: + +.. code-block:: bash + + (g * 2 * 9.80665) / (2^(resolution) - 1) * 100; for g := 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_available + 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_frequency + 200.000000 + + root:/sys/bus/iio/devices/iio:device0> cat ./in_accel_sampling_frequency_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_frequency + 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_calibbias + root:/sys/bus/iio/devices/iio:device0> echo 2 > ./in_accel_y_calibbias + root:/sys/bus/iio/devices/iio:device0> echo -250 > ./in_accel_z_calibbias + + root:/sys/bus/iio/devices/iio:device0> echo 24 > ./buffer0/length + + ## activity, threshold [62.5/LSB] + root:/sys/bus/iio/devices/iio:device0> echo 6 > ./events/in_accel_thresh_rising_value + + ## inactivity, threshold, [62.5/LSB] + root:/sys/bus/iio/devices/iio:device0> echo 4 > ./events/in_accel_thresh_falling_value + + ## inactivity, time [s] + root:/sys/bus/iio/devices/iio:device0> echo 3 > ./events/in_accel_thresh_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/in_accel_gesture_singletap_timeout + + ## doubletap, window [us] + root:/sys/bus/iio/devices/iio:device0> echo 0.025 > ./events/in_accel_gesture_doubletap_reset_timeout + + ## doubletap, latent [us] + root:/sys/bus/iio/devices/iio:device0> echo 0.025 > ./events/in_accel_gesture_doubletap_tap2_min_delay + + ## freefall, threshold [62.5/LSB] + root:/sys/bus/iio/devices/iio:device0> echo 8 > ./events/in_accel_mag_falling_value + + ## freefall, time [ms] + root:/sys/bus/iio/devices/iio:device0> echo 1.25 > ./events/in_accel_mag_falling_period + + ## activity, enable + root:/sys/bus/iio/devices/iio:device0> echo 1 > ./events/in_accel_thresh_rising_en + + ## inactivity, enable + root:/sys/bus/iio/devices/iio:device0> echo 1 > ./events/in_accel_thresh_falling_en + + ## freefall, enable + root:/sys/bus/iio/devices/iio:device0> echo 1 > ./events/in_accel_mag_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, evtype: thresh, direction: rising + Event: time: 1739063415963770218, type: accel(z), channel: 0, evtype: thresh, direction: rising + Event: time: 1739063416002563061, type: accel(z), channel: 0, evtype: gesture, direction: singletap + Event: time: 1739063426271128739, type: accel(x|y|z), channel: 0, evtype: thresh, direction: falling + Event: time: 1739063436539080713, type: accel(x|y|z), channel: 0, evtype: thresh, direction: falling + Event: time: 1739063438357970381, type: accel(z), channel: 0, evtype: thresh, direction: rising + Event: time: 1739063446726161586, type: accel(z), channel: 0, evtype: thresh, direction: rising + Event: time: 1739063446727892670, type: accel(z), channel: 0, evtype: thresh, direction: rising + Event: time: 1739063446743019768, type: accel(z), channel: 0, evtype: thresh, direction: rising + Event: time: 1739063446744650696, type: accel(z), channel: 0, evtype: thresh, direction: rising + Event: time: 1739063446763559386, type: accel(z), channel: 0, evtype: gesture, direction: singletap + Event: time: 1739063448818126480, type: accel(x|y|z), channel: 0, evtype: thresh, direction: falling + ... + +3. Device buffers +================= + +This driver supports IIO buffers. + +All devices support retrieving the raw acceleration and temperature measurements +using buffers. + +Usage examples +-------------- + +Select channels for buffer read: + +.. code-block:: bash + + 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 + +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 buffered +data is structured. + +4. IIO Interfacing Tools +======================== + +See ``Documentation/iio/iio_tools.rst`` for the description of the available IIO +interfacing tools.