From nobody Tue Dec 16 21:01:36 2025 Received: from mail-ed1-f46.google.com (mail-ed1-f46.google.com [209.85.208.46]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E598C1F5828; Mon, 21 Apr 2025 22:06:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.46 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1745273219; cv=none; b=OxavmQW7OSU4LfEoTF0toXJCHE0oonzj7EHTitaBpzlHJIrLQh+dX00964cLifwfbDh4670xKLUeQyq7egoIWzC14G2q0obu3rGxu/3o1Cd6vFDbfcm39wrza6CRkcz97/k8B9FH62YLt1gNCeo4Ma69JKuTjAeyKcZW2Qcs7o4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1745273219; c=relaxed/simple; bh=fM3+KC/UZ31kXPGTb5S0rsSfrRmlbZY6btYAdurQouc=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=JXsqtr7pNzWVVHatN47d8ojEBH0wIXTsW1h8A53Ub7r/vDUUK1wG7ri/1P/3yaJ/jxOk7TXtzIAI4QSfsFq5dIffgUVRJi2Z18MdyricF6++EZ9c5PVUGCB7sph/0gvxoZiC7GRlnqWlDhxolaE6iYPWAjlk3/b/RKy+ET3Dk0s= 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=TFRkAb65; arc=none smtp.client-ip=209.85.208.46 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="TFRkAb65" Received: by mail-ed1-f46.google.com with SMTP id 4fb4d7f45d1cf-5f4aee67d24so687119a12.0; Mon, 21 Apr 2025 15:06:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1745273216; x=1745878016; 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=TFRkAb65c0eK3khgHfBQ7rPVt7FZzH2DwJONqPmGXZQ7VlAngKPugMUFVcnquB04ca aTIob1Hr9kBsz6TyhUjeBhlFEWVpYHHV677cMtJR7pcX8RQqCRaxcVX/8h2SqpY4+R4E FqIn5lruT1+v4ucX8zbmrdz88pRt0NlzlFvD8MU+YW5/BSKJJUfod1dTR9YinoO9F93q drRrpLDf03v/i1OAHv1oFP0IS77we9DrHUlItp/UQSs3B8wRSNUZSFxDICRI8u0er/Tc +YKAkCZlAMmSweSOvyvkENztK2gN+tOMjQq02ZJjD1RQ8quLe5vRV3v6MGsE0xBJHbXE ooIg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1745273216; x=1745878016; 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=M1D6ZKHCtaXw2BJ4/VXBI2f8mRnmnp4zRk/CLvcuCaMw6mfjJtFbrvR7StE0IOTplZ KITHyI5RM4noSP0CYOE49sdVCauUx5Vo7X4Rw8voipTY4X7YQRmroF6QArH3SV1PDphF hQbfUrZaVvBkahnCUQA/53WK8jr6hrUCKbE2VhdVsvA5RHhuk/PzINSjZmbT3mx1zRtR QMu4IVdVUWzL9EmY9BycvS7IbmLI7NVDl/rGyNNKS0I6Ia+J7P5AaYRZRpRTIC1lF/wN Z+KvUi9socMefI/EeqkBOZPrygnEo3qB/yC74Acn4geBC1MXScjO9UREEXUti8L2SzzU N5+w== X-Forwarded-Encrypted: i=1; AJvYcCUAiE/QUG8peTa5jdsdNoDUVFoIncusiDhYoLHj8FoT2++zNyDyXb6M3jWSjQ4H+xS0TSqO78FEK0yfcrk=@vger.kernel.org X-Gm-Message-State: AOJu0YzOtFrt+qMXbrpUjY7Bh20mE4cTVvUnRlFQnPRJpRijy33igygr cLP7oQftahhlAahERZsaMYcyn16rPzXkTRHNBGP2vAcefUfm3OeA X-Gm-Gg: ASbGncsS7pRb2UWUn0wmBoH0DbWYZTQMnX8GRLqtT7ei8FaUqr7vvPKq8r253KgdUrY sWJztfjep2Cdf8bJvjlGpfaCzqrrKYV6Ht53k5ahOU4O1ONDYqcLMVCsbxtrkH9Xdbl/Sk+xUny +YelnrpvzMVeQEQGDPMdAEp5yC5BKhLSkvgAsmJCURo+VxTPHgfQEYCadKyPV0V9Rm7YeVokKU+ YFthre/JaJHYrUmom9LIx5fTDx2i6XnFqoHEsx6a/rge7SueMxO6Xi9nkfotSdQIUe7+w2XPXbf uFsTMqk2R+cmkBxQu26ITp8pFK0e0EuzG0fuD2EtUAaiYffj2dpaVn9Vlu0pZKS8Gfc3OmRfXz4 vcfNPwsMGceLRGk9XSJw= X-Google-Smtp-Source: AGHT+IH+fRia38DTj1g36lg7EdWidY7DqmWEJrkD8mTIjY/97kotxU8uEUvUp65F/KfYxnyTWfJgjw== X-Received: by 2002:a17:907:dab:b0:ac7:3911:250f with SMTP id a640c23a62f3a-acb74ddae97mr385152166b.14.1745273216025; Mon, 21 Apr 2025 15:06: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 a640c23a62f3a-acbb8d49fdasm80311666b.67.2025.04.21.15.06.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 21 Apr 2025 15:06: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 v7 01/11] iio: accel: adxl345: introduce adxl345_push_event function Date: Mon, 21 Apr 2025 22:06:31 +0000 Message-Id: <20250421220641.105567-2-l.rubusch@gmail.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250421220641.105567-1-l.rubusch@gmail.com> References: <20250421220641.105567-1-l.rubusch@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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_c= ore.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; } =20 +static int adxl345_push_event(struct iio_dev *indio_dev, int int_stat) +{ + struct adxl345_state *st =3D iio_priv(indio_dev); + int samples; + + if (FIELD_GET(ADXL345_INT_WATERMARK, int_stat)) { + samples =3D 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 =3D p; struct adxl345_state *st =3D iio_priv(indio_dev); int int_stat; - int samples; =20 if (regmap_read(st->regmap, ADXL345_REG_INT_SOURCE, &int_stat)) return IRQ_NONE; =20 - if (FIELD_GET(ADXL345_INT_WATERMARK, int_stat)) { - samples =3D 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; =20 if (FIELD_GET(ADXL345_INT_OVERRUN, int_stat)) goto err; --=20 2.39.5 From nobody Tue Dec 16 21:01:36 2025 Received: from mail-ej1-f45.google.com (mail-ej1-f45.google.com [209.85.218.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 2F70521B9F5; Mon, 21 Apr 2025 22:06:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.45 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1745273221; cv=none; b=jxMX3L7XHBQPrgy7f4FdK+TJ34dc1rplJD+00ANBEYS0O111R/jo/wiF8g2f2ry5KF54XhYWDv8nu+xJPLc7Q0auQFWmH5k/sa1wvn8KhHN1Gt1SGVEUKUveTMZIX8W7SUYKA29nR1RvEXCWRpzN9l4OMwFsejP1iOM7D+erq/8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1745273221; c=relaxed/simple; bh=5RxrPYtZ7I6Dt5qarm4tttwb4MttmZTzMw61EXrH4Qc=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=LyTefYKsHVvewsY7GREAzBpXmo4pRuqZT6y6KXaADARS0sH93DkrfEL7+ct5ASXonbUaJQBgdMF38MH0QRbgJoGhCILVvfUyMbQ14x/jwr6rY8iN3XvQ2gibZ2u6+VC8wdYoWejJcpo7Pm1c2/oQ9tKHuv1jO9pW+iopeWIQyiE= 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=YN0gz2Am; arc=none smtp.client-ip=209.85.218.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="YN0gz2Am" Received: by mail-ej1-f45.google.com with SMTP id a640c23a62f3a-ac3beea7762so47778966b.2; Mon, 21 Apr 2025 15:06:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1745273217; x=1745878017; 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=pfWNkGnK7ineJbQkLTaDbBS+hsswOkVBZ94MBtsFSmo=; b=YN0gz2AmJnDJ+p7TScxDPmmgsmfncQLADP3Cz3qP6rDwJJDfyOt0OdudK+PcGO+ZiS 4taPdUekoWhuShtv5Ghra8yX1n33OCbBFICqxpufxcZ7gx7HNHx6aj14cxamv2JdQVhG KRk6INqXSS9fUFTPY2Hs89Gu3BEf8dD5MQQUJPrzzk1cbkALg6uRwWv5u2L3e9uvleQ+ r5yH2zuV6GDxVY4ivExIpOoFDQhbr6DKwpNMEoyhjQORS3dEX8ryUYIYYqWuVdipyw1O REaDLqQN3uzAVLO44Op+3jw8y+qHE9YhrUHQ6ksGQGcwTV2uBq1w7wszfXO+0LTVNxkO tOfA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1745273217; x=1745878017; 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=pfWNkGnK7ineJbQkLTaDbBS+hsswOkVBZ94MBtsFSmo=; b=MgxlJ8mL/99kV1iDC+9lUoeelhR2bqkcdlAgWeDZcCmbZoVCd+Z+cyD/Pt+iLkHyDr nj9MrYr/u+eErUN/+uJhK8VBjHnRImVD2UO6x7U5gOX/K71L/eAAYmV7abcsrWfax4s7 H0C2F8ukELNWzqIjBmEkZwPUFT1YVou+jJfMhoyqVgj993sOLrPRGvy7Hqgi2FcO4/6q c4vh/iqfOZwOUoT9+GnebqAglxFzOqAYHXrD5pyBPZX66GRRRa10Tw644Oqcl7ZxG2mf vdEE9iI4/ubBbefZ8dE34rh6rwF62E9kUae8o5I9IJz2xuAuCXadyOOdy+Lul2ZAwC2X BTBg== X-Forwarded-Encrypted: i=1; AJvYcCWr0fEdSV3v0tWJ9/qVuK/f4OWS/xp4dXQyaAezIODgKAuHwb34I8/0z2DozLk+J1QtMvztBcIDix+Zwic=@vger.kernel.org X-Gm-Message-State: AOJu0YxoJUdeOocb5DrHj4G8d/OXp9Zv1hkQMzw1ZXb2McY4nprhiwHu Nk/LC+nqXo6mmIZJ4+Sc5amoPQ6tiWtvGPCS1NjFX2V83fEMLxKx X-Gm-Gg: ASbGncsXLKKCCaahNiNkQjIa3SejwlPU/wUHxWBRrDlnx0AlNCromFxq8dHnBY9reSv Wfgjps/RJzlSlyqC9xcwAfPOPUJbPTYNkxA9cDNDWmoe4JW6oSnbB6E7g/zsPdXCJVhQdGLfTpy r6bGHXwb9qgPwS+UGbOvN8+gKGtxsxSxLUwlVakacZiRCke4zIbxvpb0sH4GUnmQ/Y/u2xQKeup ViRkjf38YEpiFEyCVAArMvC+0i/2qC8wM6TadX/iGnAuQ6TRLWJb20Rt3OVLDrfk0eshre9o+CB D9fOcPC/UgM6vxbZVlo4BuLNHtwnbGeHHjjVfx99Ggs7J8aS7hT+3bxRDAED5y6oUd3Jhn6qHQU K6p558Xvl4SIV8gPz8Zo= X-Google-Smtp-Source: AGHT+IFUhJwpwGVnNEPMcNIY7Y/swwFa8hZi7e2Cv3eUjckmlC7c6cMdCPr6/bJYEhFtGZArDUsQ8Q== X-Received: by 2002:a17:907:7f22:b0:abf:6166:d0e8 with SMTP id a640c23a62f3a-acb74ad4447mr360923066b.3.1745273217071; Mon, 21 Apr 2025 15:06: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 a640c23a62f3a-acbb8d49fdasm80311666b.67.2025.04.21.15.06.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 21 Apr 2025 15:06:56 -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 v7 02/11] iio: accel: adxl345: add single tap feature Date: Mon, 21 Apr 2025 22:06:32 +0000 Message-Id: <20250421220641.105567-3-l.rubusch@gmail.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250421220641.105567-1-l.rubusch@gmail.com> References: <20250421220641.105567-1-l.rubusch@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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 | 372 ++++++++++++++++++++++++++++++- 1 file changed, 369 insertions(+), 3 deletions(-) diff --git a/drivers/iio/accel/adxl345_core.c b/drivers/iio/accel/adxl345_c= ore.c index a98fb7fc748e..ccb25c35ac07 100644 --- a/drivers/iio/accel/adxl345_core.c +++ b/drivers/iio/accel/adxl345_core.c @@ -8,6 +8,7 @@ */ =20 #include +#include #include #include #include @@ -17,6 +18,7 @@ #include #include #include +#include #include =20 #include "adxl345.h" @@ -31,6 +33,29 @@ #define ADXL345_INT1 0 #define ADXL345_INT2 1 =20 +#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[] =3D { + [ADXL345_SINGLE_TAP] =3D ADXL345_INT_SINGLE_TAP, +}; + +enum adxl345_tap_time_type { + ADXL345_TAP_TIME_DUR, +}; + +static const unsigned int adxl345_tap_time_reg[] =3D { + [ADXL345_TAP_TIME_DUR] =3D 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_M= INALIGN); }; =20 +static struct iio_event_spec adxl345_events[] =3D { + { + /* single tap */ + .type =3D IIO_EV_TYPE_GESTURE, + .dir =3D IIO_EV_DIR_SINGLETAP, + .mask_separate =3D BIT(IIO_EV_INFO_ENABLE), + .mask_shared_by_type =3D BIT(IIO_EV_INFO_VALUE) | + BIT(IIO_EV_INFO_TIMEOUT), + }, +}; + #define ADXL345_CHANNEL(index, reg, axis) { \ .type =3D IIO_ACCEL, \ .modified =3D 1, \ @@ -57,6 +96,8 @@ struct adxl345_state { .storagebits =3D 16, \ .endianness =3D IIO_LE, \ }, \ + .event_spec =3D adxl345_events, \ + .num_event_specs =3D ARRAY_SIZE(adxl345_events), \ } =20 enum adxl345_chans { @@ -113,6 +154,157 @@ static int adxl345_set_measure_en(struct adxl345_stat= e *st, bool en) return regmap_write(st->regmap, ADXL345_REG_POWER_CTL, val); } =20 +/* tap */ + +static int _adxl345_set_tap_int(struct adxl345_state *st, + enum adxl345_tap_type type, bool state) +{ + unsigned int int_map =3D 0x00; + unsigned int tap_threshold; + bool axis_valid; + bool singletap_args_valid =3D false; + bool en =3D false; + u32 axis_ctrl; + int ret; + + ret =3D regmap_read(st->regmap, ADXL345_REG_TAP_AXIS, &axis_ctrl); + if (ret) + return ret; + + axis_valid =3D FIELD_GET(ADXL345_REG_TAP_AXIS_MSK, axis_ctrl) > 0; + + ret =3D 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 =3D tap_threshold > 0 && st->tap_duration_us > 0; + + if (type =3D=3D ADXL345_SINGLE_TAP) + en =3D axis_valid && singletap_args_valid; + + if (state && en) + int_map |=3D 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; + u32 axis_ctrl; + int ret; + + ret =3D regmap_read(st->regmap, ADXL345_REG_TAP_AXIS, &axis_ctrl); + if (ret) + return ret; + + /* Verify if axis is enabled for the tap detection. */ + switch (axis) { + case IIO_MOD_X: + *en =3D FIELD_GET(ADXL345_TAP_X_EN, axis_ctrl); + break; + case IIO_MOD_Y: + *en =3D FIELD_GET(ADXL345_TAP_Y_EN, axis_ctrl); + break; + case IIO_MOD_Z: + *en =3D FIELD_GET(ADXL345_TAP_Z_EN, axis_ctrl); + break; + default: + *en =3D false; + return -EINVAL; + } + + if (*en) { + /* + * If axis allow for tap detection, verify if the interrupt is + * enabled for tap detection. + */ + ret =3D regmap_read(st->regmap, ADXL345_REG_INT_ENABLE, ®val); + if (ret) + return ret; + + *en =3D adxl345_tap_int_reg[type] & regval; + } + + 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 =3D ADXL345_TAP_X_EN; + break; + case IIO_MOD_Y: + axis_ctrl =3D ADXL345_TAP_Y_EN; + break; + case IIO_MOD_Z: + axis_ctrl =3D ADXL345_TAP_Z_EN; + break; + default: + return -EINVAL; + } + + if (en) + ret =3D regmap_set_bits(st->regmap, ADXL345_REG_TAP_AXIS, + axis_ctrl); + else + ret =3D 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 =3D 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 =3D=3D ADXL345_TAP_TIME_DUR) + regval =3D DIV_ROUND_CLOSEST(val_us, 625); + else + regval =3D 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 =3D 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 +390,131 @@ static int adxl345_write_raw(struct iio_dev *indio_de= v, return -EINVAL; } =20 +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 =3D iio_priv(indio_dev); + bool int_en; + int ret; + + switch (type) { + case IIO_EV_TYPE_GESTURE: + switch (dir) { + case IIO_EV_DIR_SINGLETAP: + ret =3D 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, + bool state) +{ + struct adxl345_state *st =3D 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 =3D 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 =3D 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 =3D regmap_read(st->regmap, ADXL345_REG_THRESH_TAP, + &tap_threshold); + if (ret) + return ret; + *val =3D sign_extend32(tap_threshold, 7); + return IIO_VAL_INT; + case IIO_EV_INFO_TIMEOUT: + *val =3D st->tap_duration_us; + *val2 =3D 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 =3D iio_priv(indio_dev); + int ret; + + ret =3D 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 =3D regmap_write(st->regmap, ADXL345_REG_THRESH_TAP, + min(val, 0xFF)); + if (ret) + return ret; + break; + case IIO_EV_INFO_TIMEOUT: + ret =3D 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 +733,23 @@ static int adxl345_fifo_push(struct iio_dev *indio_de= v, return 0; } =20 -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 =3D iio_get_time_ns(indio_dev); struct adxl345_state *st =3D iio_priv(indio_dev); int samples; + int ret =3D -ENOENT; + + if (FIELD_GET(ADXL345_INT_SINGLE_TAP, int_stat)) { + ret =3D 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; + } =20 if (FIELD_GET(ADXL345_INT_WATERMARK, int_stat)) { samples =3D adxl345_get_samples(st); @@ -428,9 +758,11 @@ static int adxl345_push_event(struct iio_dev *indio_de= v, int int_stat) =20 if (adxl345_fifo_push(indio_dev, samples) < 0) return -EINVAL; + + ret =3D 0; } =20 - return 0; + return ret; } =20 /** @@ -444,12 +776,33 @@ static irqreturn_t adxl345_irq_handler(int irq, void = *p) { struct iio_dev *indio_dev =3D p; struct adxl345_state *st =3D iio_priv(indio_dev); + unsigned int regval; + enum iio_modifier tap_dir =3D IIO_NO_MOD; + u32 axis_ctrl; int int_stat; + int ret; + + ret =3D 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 =3D 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 =3D IIO_MOD_Z; + else if (FIELD_GET(ADXL345_TAP_Y_EN, regval)) + tap_dir =3D IIO_MOD_Y; + else if (FIELD_GET(ADXL345_TAP_X_EN, regval)) + tap_dir =3D IIO_MOD_X; + } =20 if (regmap_read(st->regmap, ADXL345_REG_INT_SOURCE, &int_stat)) return IRQ_NONE; =20 - if (adxl345_push_event(indio_dev, int_stat)) + if (adxl345_push_event(indio_dev, int_stat, tap_dir)) goto err; =20 if (FIELD_GET(ADXL345_INT_OVERRUN, int_stat)) @@ -468,6 +821,10 @@ static const struct iio_info adxl345_info =3D { .read_raw =3D adxl345_read_raw, .write_raw =3D adxl345_write_raw, .write_raw_get_fmt =3D adxl345_write_raw_get_fmt, + .read_event_config =3D adxl345_read_event_config, + .write_event_config =3D adxl345_write_event_config, + .read_event_value =3D adxl345_read_event_value, + .write_event_value =3D adxl345_write_event_value, .debugfs_reg_access =3D &adxl345_reg_access, .hwfifo_set_watermark =3D adxl345_set_watermark, }; @@ -501,6 +858,7 @@ int adxl345_core_probe(struct device *dev, struct regma= p *regmap, ADXL345_DATA_FORMAT_JUSTIFY | ADXL345_DATA_FORMAT_FULL_RES | ADXL345_DATA_FORMAT_SELF_TEST); + unsigned int tap_threshold; int ret; =20 indio_dev =3D devm_iio_device_alloc(dev, sizeof(*st)); @@ -514,6 +872,10 @@ int adxl345_core_probe(struct device *dev, struct regm= ap *regmap, return -ENODEV; st->fifo_delay =3D fifo_delay_default; =20 + /* Init with reasonable values */ + tap_threshold =3D 48; /* 48 [0x30] -> ~3g */ + st->tap_duration_us =3D 16; /* 16 [0x10] -> .010 */ + indio_dev->name =3D st->info->name; indio_dev->info =3D &adxl345_info; indio_dev->modes =3D INDIO_DIRECT_MODE; @@ -586,6 +948,10 @@ int adxl345_core_probe(struct device *dev, struct regm= ap *regmap, if (ret) return ret; =20 + ret =3D regmap_write(st->regmap, ADXL345_REG_THRESH_TAP, tap_threshold); + if (ret) + return ret; + /* FIFO_STREAM mode is going to be activated later */ ret =3D devm_iio_kfifo_buffer_setup(dev, indio_dev, &adxl345_buffer_ops); if (ret) --=20 2.39.5 From nobody Tue Dec 16 21:01:36 2025 Received: from mail-ed1-f51.google.com (mail-ed1-f51.google.com [209.85.208.51]) (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 3A36821D5A6; Mon, 21 Apr 2025 22:06:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.51 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1745273222; cv=none; b=Ssk9dz2xlp4WpOcBDMW0Sd8wYbwrfatzZQD7OF/wt+bakHliIzUjKQ9+jdwt/HP2Hdd1jya0XvlOONZ/RyKS0sXNYMvWx4COOmIOGcOKz8IseiKOa8ONDI4gon2oSZocf6j8s+4n28D0Kc4mBG7EhjouowId7JJ9kHH3muPpAMA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1745273222; c=relaxed/simple; bh=0CGAbwxTgGMgGM/mr6uEkMLoVL7t36cFFW8BH3LDQe4=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=cNWfc9As/KT8X9u+r1avq71S28vwLnNnybsLVohOLnc7FV4LNVss/vIi2f6I+3SSH/G2Oiixdw+KvNQmC9FewKXswb7GNM8aebnoKkGCt40D0d5K9mH+d+NVqpsJrCIiJTmueHA/IyiBkxnNFEqlL7ICN8N5UE7CtktTxgf0lTw= 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=OmLvN31b; arc=none smtp.client-ip=209.85.208.51 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="OmLvN31b" Received: by mail-ed1-f51.google.com with SMTP id 4fb4d7f45d1cf-5f4aee67d24so687125a12.0; Mon, 21 Apr 2025 15:06:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1745273218; x=1745878018; 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=YkNLtfmEhNo02EFqwGf9GufdancWAgw/DN+zWQihpvw=; b=OmLvN31bNwOfdALnb/nI9IsGCNC0N7RyvzQJCRNsCzqwFssYoXoA8+Mti9OTCvcfsw pklQawucqrjQ/Eq2oEXzFUEtybLuctcQ8e3T45Xq/ps7uriMk96m87v6zaSgIujgwPPJ /IexnUJFe1nl25wlCf+ESpZO+YZN/2WlNMaD4vTVm2M5DPg1JjQWWT4F5dSVrXfMV35C +NRf1RM9SPTJ4/GmGAvXVbNaewOYtJ4sshffSyg4aCH7fopnhyiFhjJ9Qjcmj3beBkzT OObjIyaA00h3tzpWQ5YqHPmNqvqhAHpOnJmduhtkcCmwGoH2g4GcRw15XpT9dq1h6EPw uP2g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1745273218; x=1745878018; 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=YkNLtfmEhNo02EFqwGf9GufdancWAgw/DN+zWQihpvw=; b=jf0M/K0dBvlVIYimkoalXm2PskbqhxxUM4TVP9fuAlHevOkUpNI+6OEBZEatzTZXvK l9pQ8r4mzxg+uFwDrhUAgblhatN8eoeUwXXMvwMH6ORm9Z6My+ySZagVJUF2BU/w1fwu 2D6JgyT3zPd9H+K0rDeKHf/xytYoeUhD9ddZGL5Sd0kOSOZGrBx/jc+Py9DBOjRm6bvm THEimTWbHzLf+JoiGUkjv5gd9UmrTwKn3btgsn+oCvA/gzKjJTATRF0TWpUxjk+QRkCt n4+Umc/Q+it2TQHAb6k0ZiZ1piU2r9RQbuXrqaCo0A95NOQi73ZWAVIe1n4jNNCQI9yT E0QA== X-Forwarded-Encrypted: i=1; AJvYcCV6W3+hQEJqNS/IaKG0SwSAeZdQkq4PAs/fbKobPANrBBp2f4ixhvtgohHSd+LIYK1zrqgG3CCHfTx9JC8=@vger.kernel.org X-Gm-Message-State: AOJu0Yzkqj4uqADbjRjYNyTxSk+nKa8rl/mNWXPHpAH4kQzmQlrwMUid oCLaDiL18ZWCZBSa1WvLX6cZ4uxUO57FI7SPyWxQ4KrfJL95VeiC X-Gm-Gg: ASbGnct68GQNxMvIa5lNqzTpG+3gUb4b1dyeqP1dHP1GQGBmOqjuKLpltkraCxoSXUg JgSvHfpjVL2uHo2yrT1dyTNm5iJ5XDoJnFj2z2kvXk8yeL5Bpv5K+n+375ln48Gw8jjtxFeQgzR LHrARbmGFVTH3Zf1iX1d1pJI5vqYU8D2Ss+OGGYJn3f26pljf+7evZ7WoQ+wePap8sSEsO0PS9T WT38fdhwm91LXLIlKpR6t8TVorsSSCqqGlALBpmsvnaWdi7OI5BXK1dT+0b1A2fyK+Y48jRwI1t H3ydOKRam3iojQi7braRfD5j1lFLr04JuBUmiEh99b/nC3Zfe2tP4t0iR6qVj40KjMM6KS6RkU3 1eXDliuvFYVRTdkuipTU= X-Google-Smtp-Source: AGHT+IETRtU5lnTIaLpR3LqRp0jjMXiVG83gsf0dIwLApwBmafuhK+qzTa6+XlGlsfQ84KHHy5Q24A== X-Received: by 2002:a17:906:f5a5:b0:ac2:6bf9:e386 with SMTP id a640c23a62f3a-acb74b80cb5mr381911366b.8.1745273218112; Mon, 21 Apr 2025 15:06: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 a640c23a62f3a-acbb8d49fdasm80311666b.67.2025.04.21.15.06.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 21 Apr 2025 15:06: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 v7 03/11] iio: accel: adxl345: add double tap feature Date: Mon, 21 Apr 2025 22:06:33 +0000 Message-Id: <20250421220641.105567-4-l.rubusch@gmail.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250421220641.105567-1-l.rubusch@gmail.com> References: <20250421220641.105567-1-l.rubusch@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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_c= ore.c index ccb25c35ac07..a95f1c218c0c 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, }; =20 static const unsigned int adxl345_tap_int_reg[] =3D { [ADXL345_SINGLE_TAP] =3D ADXL345_INT_SINGLE_TAP, + [ADXL345_DOUBLE_TAP] =3D ADXL345_INT_DOUBLE_TAP, }; =20 enum adxl345_tap_time_type { + ADXL345_TAP_TIME_LATENT, + ADXL345_TAP_TIME_WINDOW, ADXL345_TAP_TIME_DUR, }; =20 static const unsigned int adxl345_tap_time_reg[] =3D { + [ADXL345_TAP_TIME_LATENT] =3D ADXL345_REG_LATENT, + [ADXL345_TAP_TIME_WINDOW] =3D ADXL345_REG_WINDOW, [ADXL345_TAP_TIME_DUR] =3D ADXL345_REG_DUR, }; =20 @@ -65,6 +71,8 @@ struct adxl345_state { u8 fifo_mode; =20 u32 tap_duration_us; + u32 tap_latent_us; + u32 tap_window_us; =20 __le16 fifo_buf[ADXL345_DIRS * ADXL345_FIFO_SIZE + 1] __aligned(IIO_DMA_M= INALIGN); }; @@ -78,6 +86,14 @@ static struct iio_event_spec adxl345_events[] =3D { .mask_shared_by_type =3D BIT(IIO_EV_INFO_VALUE) | BIT(IIO_EV_INFO_TIMEOUT), }, + { + /* double tap */ + .type =3D IIO_EV_TYPE_GESTURE, + .dir =3D IIO_EV_DIR_DOUBLETAP, + .mask_shared_by_type =3D BIT(IIO_EV_INFO_ENABLE) | + BIT(IIO_EV_INFO_RESET_TIMEOUT) | + BIT(IIO_EV_INFO_TAP2_MIN_DELAY), + }, }; =20 #define ADXL345_CHANNEL(index, reg, axis) { \ @@ -163,6 +179,7 @@ static int _adxl345_set_tap_int(struct adxl345_state *s= t, unsigned int tap_threshold; bool axis_valid; bool singletap_args_valid =3D false; + bool doubletap_args_valid =3D false; bool en =3D false; u32 axis_ctrl; int ret; @@ -183,8 +200,16 @@ static int _adxl345_set_tap_int(struct adxl345_state *= st, */ singletap_args_valid =3D tap_threshold > 0 && st->tap_duration_us > 0; =20 - if (type =3D=3D ADXL345_SINGLE_TAP) + if (type =3D=3D ADXL345_SINGLE_TAP) { en =3D axis_valid && singletap_args_valid; + } else { + /* doubletap: Window must be equal or greater than latent! */ + doubletap_args_valid =3D st->tap_latent_us > 0 && + st->tap_window_us > 0 && + st->tap_window_us >=3D st->tap_latent_us; + + en =3D axis_valid && singletap_args_valid && doubletap_args_valid; + } =20 if (state && en) int_map |=3D adxl345_tap_int_reg[type]; @@ -268,12 +293,23 @@ static int adxl345_set_singletap_en(struct adxl345_st= ate *st, return _adxl345_set_tap_int(st, ADXL345_SINGLE_TAP, en); } =20 +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; =20 switch (type) { + case ADXL345_TAP_TIME_WINDOW: + st->tap_window_us =3D val_us; + break; + case ADXL345_TAP_TIME_LATENT: + st->tap_latent_us =3D val_us; + break; case ADXL345_TAP_TIME_DUR: st->tap_duration_us =3D val_us; break; @@ -305,6 +341,34 @@ static int adxl345_set_tap_duration(struct adxl345_sta= te *st, u32 val_int, return _adxl345_set_tap_time(st, ADXL345_TAP_TIME_DUR, val_fract_us); } =20 +static int adxl345_set_tap_window(struct adxl345_state *st, u32 val_int, + u32 val_fract_us) +{ + /* + * Max value is 255 * 1250 us =3D 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 =3D 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) @@ -408,6 +472,12 @@ static int adxl345_read_event_config(struct iio_dev *i= ndio_dev, if (ret) return ret; return int_en; + case IIO_EV_DIR_DOUBLETAP: + ret =3D adxl345_is_tap_en(st, chan->channel2, + ADXL345_DOUBLE_TAP, &int_en); + if (ret) + return ret; + return int_en; default: return -EINVAL; } @@ -429,6 +499,8 @@ static int adxl345_write_event_config(struct iio_dev *i= ndio_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; } @@ -468,6 +540,14 @@ static int adxl345_read_event_value(struct iio_dev *in= dio_dev, *val =3D st->tap_duration_us; *val2 =3D 1000000; return IIO_VAL_FRACTIONAL; + case IIO_EV_INFO_RESET_TIMEOUT: + *val =3D st->tap_window_us; + *val2 =3D 1000000; + return IIO_VAL_FRACTIONAL; + case IIO_EV_INFO_TAP2_MIN_DELAY: + *val =3D st->tap_latent_us; + *val2 =3D 1000000; + return IIO_VAL_FRACTIONAL; default: return -EINVAL; } @@ -504,6 +584,16 @@ static int adxl345_write_event_value(struct iio_dev *i= ndio_dev, if (ret) return ret; break; + case IIO_EV_INFO_RESET_TIMEOUT: + ret =3D adxl345_set_tap_window(st, val, val2); + if (ret) + return ret; + break; + case IIO_EV_INFO_TAP2_MIN_DELAY: + ret =3D adxl345_set_tap_latent(st, val, val2); + if (ret) + return ret; + break; default: return -EINVAL; } @@ -751,6 +841,16 @@ static int adxl345_push_event(struct iio_dev *indio_de= v, int int_stat, return ret; } =20 + if (FIELD_GET(ADXL345_INT_DOUBLE_TAP, int_stat)) { + ret =3D 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 =3D adxl345_get_samples(st); if (samples < 0) @@ -875,6 +975,8 @@ int adxl345_core_probe(struct device *dev, struct regma= p *regmap, /* Init with reasonable values */ tap_threshold =3D 48; /* 48 [0x30] -> ~3g */ st->tap_duration_us =3D 16; /* 16 [0x10] -> .010 */ + st->tap_window_us =3D 64; /* 64 [0x40] -> .080 */ + st->tap_latent_us =3D 16; /* 16 [0x10] -> .020 */ =20 indio_dev->name =3D st->info->name; indio_dev->info =3D &adxl345_info; --=20 2.39.5 From nobody Tue Dec 16 21:01:36 2025 Received: from mail-ej1-f46.google.com (mail-ej1-f46.google.com [209.85.218.46]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E2B8D2206B5; Mon, 21 Apr 2025 22:07:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.46 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1745273222; cv=none; b=ZGla7C7RUzR6a0QESYGH2ji2H0z+UgPQaFiqY0suN/9CYUg/MJ4n6a1cBolEQPWexWg0R3YmdUlVfh9Ghl8IyACIX0SYdn4r58bx9CKxY5dYzdv334Eeb89Y3IeB52X9uYXrCUCTP6sIsW2xQL9x2Y/YjPzwKC3WJa4T1uBJGAA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1745273222; c=relaxed/simple; bh=rbaYOkUTWpyowR7jBDQPIChL648feaPDsQw7fIdQNGE=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=KW3NR/6furRScYHZ485bfgOjTdOnG7lv6wvhW1F2QXHwvSA11AcGvcxZwz1p6dctqPpQW0RrkWQgISJyEynpWmhYqFwLADAjGuBBpMLZz5QSf4bE4Nqy3+q+Td0FQLGfbKCxSxQMxHDqyfwmwKKJo/IW+Z90VOZcs5okTlklH/E= 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=fZiNeOj1; arc=none smtp.client-ip=209.85.218.46 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="fZiNeOj1" Received: by mail-ej1-f46.google.com with SMTP id a640c23a62f3a-acb94bf7897so16152966b.3; Mon, 21 Apr 2025 15:07:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1745273219; x=1745878019; 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=6IPG/e3mCWKEPm+RsqHpGKWjD98/6RuMtaJowuJZ564=; b=fZiNeOj1TqVYJ5dBNXlrRDYpbWc4L7kZG/QFfwNFqUrZDL+NlYR7BSJPbkAOVP+TOw Alz7/HZlU27sAcgy+IXye6SHvaPQRzDpDInW1r4F4Ad6eDX7shUzK1dpbAbWJD9AyZvC oECdhKGT22NilZ7imktFS3XV0Ltt+RAtqV1/8SVK066lLoMk6+HYyKDbm6EYnkZ4JONf /33rNFAIEkCG3AfvzC3bA+JoO9VEbY88T8wslCoBL0aE19ZCK/5evt30zuJLowYHetxI VdulibRv5ugjFqY0TbBiJ64olwTTheoubIkSY9MY63u4H2FdshT5oqKyIeYJfLIzm7Iq TakA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1745273219; x=1745878019; 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=6IPG/e3mCWKEPm+RsqHpGKWjD98/6RuMtaJowuJZ564=; b=J7LUsgBSuoJQiJUcdUFRIsIicnWRyjTaTj0WIX9cYrzvhwOQNkrZqosamI6ZEFT124 vekwt4vfNMNVPEdq9PZ0giKOIR8oizGbE+85C4wYgCsesDkLv7cSJzfMtxFZzyIYvUEV DgAZ+ZcS20VEswTO3EkT2mVnMq8Pk2GTVhXRb09qh7KB9gSZzg2j4qTGU+fGzmzI1Com yCAjargzVR+/8oafHHiYvBIG9UkM+mNDt1jueWX+3JePTUatZGPJlUmjahbVOSHMm51/ kUhUdYiyMNd29VhPokwKSJePDNWi5kq8K4/vxE70d8iGPGx4P2claxbL9MPYFaDGgzyi WBWg== X-Forwarded-Encrypted: i=1; AJvYcCWLzxclXALyqDUPRNMjLrEeRXRxWzZRWSfecIIOS0/+rQuwe7MFsjpPFGXGqIKzzou7KR9vUE5lrs7I9Zw=@vger.kernel.org X-Gm-Message-State: AOJu0Yzt1WobH4GU2l11VyOwS8bMcVB79WVwkFoIoAKTu6JIi0ZeamI+ ygqTogoVph6xYinJ7kl0ES4aULElmoNJYQy2c+MJQHpKr0SmXp0/ X-Gm-Gg: ASbGncvuKPdmdsu0b5SPBc/xU9On5Xfkdu56F1Uiyv1lIJAh0tGE0VQZC5N7X3SPP/j tQywhIUutYhqcCv/X/3VlYbnrM7ZQy1o0KXb9Nku6FtRv75hrmKzsLkMwuTu4gPuwiuAXu1ld2i ZWWYYU+um/pWxYAwtmW1N+jshJNnH4uC8/x4sqBDIClQBgToBuNeyRMSZ3tQXuU7jeNA8fb4MMe xq41ZeF52Vd8TxSlAg45cuRLK/edNIkcCAV8wwaX4OYjAOEY3h1zO35N+rPngEd22GWa+vp4y0y MQmmncUb+ySkHZwc/aLHsIF0cpw9rD9G2Evp2CwBMks1/TYmYPoxoUTVmU75HRplj9cH6GtegZr CybbB3lmjlF6i3uGd3GU= X-Google-Smtp-Source: AGHT+IHLX5K7GK3CQD1L0U97V4n9HNL9+lA0XCwdtDzi0mU5FjZ+DRj1B8DJxjGj6g+ijXLHEnyfCQ== X-Received: by 2002:a17:907:7d8a:b0:acb:1e98:1a19 with SMTP id a640c23a62f3a-acb74b80bafmr328664366b.8.1745273218988; Mon, 21 Apr 2025 15:06: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 a640c23a62f3a-acbb8d49fdasm80311666b.67.2025.04.21.15.06.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 21 Apr 2025 15:06: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 v7 04/11] iio: accel: adxl345: set the tap suppress bit permanently Date: Mon, 21 Apr 2025 22:06:34 +0000 Message-Id: <20250421220641.105567-5-l.rubusch@gmail.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250421220641.105567-1-l.rubusch@gmail.com> References: <20250421220641.105567-1-l.rubusch@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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_c= ore.c index a95f1c218c0c..c464c87033fb 100644 --- a/drivers/iio/accel/adxl345_core.c +++ b/drivers/iio/accel/adxl345_core.c @@ -34,6 +34,8 @@ #define ADXL345_INT2 1 =20 #define ADXL345_REG_TAP_AXIS_MSK GENMASK(2, 0) +#define ADXL345_REG_TAP_SUPPRESS_MSK BIT(3) +#define ADXL345_REG_TAP_SUPPRESS BIT(3) =20 #define ADXL345_TAP_Z_EN BIT(0) #define ADXL345_TAP_Y_EN BIT(1) @@ -295,6 +297,18 @@ static int adxl345_set_singletap_en(struct adxl345_sta= te *st, =20 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 =3D 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); } =20 --=20 2.39.5 From nobody Tue Dec 16 21:01:36 2025 Received: from mail-ed1-f54.google.com (mail-ed1-f54.google.com [209.85.208.54]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A3EA5221541; Mon, 21 Apr 2025 22:07:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.54 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1745273223; cv=none; b=NWEVXnf0LiRQPLDxMb7/g8rvO+FUSM8p0pcQSoGeQXjXQzYBKNx4VCD9qUhIz94VJ35f3KUet2XaHqVi8yYXb6fmRBTgllVVlc9C2bOjGbZT3h0rLM7ywmz/HVt28bfH/RznZrHRfGNAdLO39uGUC/O/VMpN6CCMgTUBiKXhitQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1745273223; c=relaxed/simple; bh=u7HugNoxWSUaNP1adimKDBkibD2dTkBd882ZzUDDWBg=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=pDi6tiw5+kv7kC3a0vu6Bkm+e6Uw7fvjma5A4UbFBe3UBiDkt/AfJOk3yoAWkLOXDwDoUB2pXztikkLNe4n03V6czVkf1EqI/usUdf2erfRSoMjLT3eqQqmR2rglyWR+qTtWVpcANeBdAJsfWWZz5Q72Os6KlxccfTuLpKuH8ew= 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=mPdUh/iN; arc=none smtp.client-ip=209.85.208.54 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="mPdUh/iN" Received: by mail-ed1-f54.google.com with SMTP id 4fb4d7f45d1cf-5f37f45e819so704864a12.3; Mon, 21 Apr 2025 15:07:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1745273220; x=1745878020; 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=yfTlM7bYUKW+qdxuoRFzRPDEGnqKN2kxZUE8Rurfp7U=; b=mPdUh/iNY2FRh9FR5q13GKYJWHKfW6uJZenfPb80wIi9SKbpzGu9opqYr6XxQIUfa6 pmTS+QQOjJfDPouF/C2KXG2vl6vaXhp6w5kHjbF1AMPGtK0ZfTYxNgLdAGnm7LhNLLqe DfTiwLgrxedQsMe6NvK/0ZY3U7IA4bcZzeFXMTgzcVkn/eCMUKBuQ2pYflDqfsbj7Jkl xWjanNOolmSGepBQOmDTaNTJVPWfuQrdCA5pVFS3tI3YYPXUKpSoYe3k6Eau+DOZqBJg l9a1SnsXdxoZchQvZwDjSxSXZdBpQ/PATPytJPnQeMoKs73aQa4bC1LH3frjGH5EaGeU 1p9Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1745273220; x=1745878020; 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=yfTlM7bYUKW+qdxuoRFzRPDEGnqKN2kxZUE8Rurfp7U=; b=UDTqDDSyyJ9N41Is2DizdGpAUVAqaZ+M2ZQ2vVhL4agToh4Z2P2qXkIwpzaCfRF1sa AknCA4MAjHIi/LKNOqwSjYPiqZFZWC1lxBFWqYXd6/+OSAP7jWEHktkInEYVHp/EFlJv 7XsQQuCvOesqx9syV8iwxXUf3Ub94EIV8iCW1GdMhXTErFu9Y3GZB+W/iSwJy2pYmIkR ZsygXJv2WEaUegCBZBI39phAg0vagKXY53dj4ZNtm2rlS8K4Vp+nQbwA0uhtY9AOsiz6 1/ono0KffBf20b9qSCv7gAmE/uVgzniCts0fR0i3SOIMJoqa+t4TzvUTxRXINSj4Z/K3 jUDg== X-Forwarded-Encrypted: i=1; AJvYcCW39LhsBA2afVQwSmmun/Fg/iqkjrtHDgf7sOwMR8edRlG4101KedbVHFdwAO8Yd44MhguhSkqiHM5yWDU=@vger.kernel.org X-Gm-Message-State: AOJu0YxPlvBU/qvhtSyw9ub3EOgqYdxM7iXuKXvi7uAog8h5E5sHr1ar b5LWXHIDizFNnHzrb498xVJ2ZK2fD0Mir1dFuwI6wDB0W3KGWcAM X-Gm-Gg: ASbGncvgTb4cBVWGrvEqsndqkzmpn0/BeORAWbNkYBmpd2qgvdzEFyJWmQ+c9PwFZqD k1CXRhHMfaK8hZHZVu+fZ1GRsvsYFYFaddg69CKDZGncJpG+tR1UB4DznxO69XiTKcNgD3NcPy6 sMVOX7kbLBOck4QZ08WHypkBg+9hnctTEfg9o7p8lYSNco6tvKwLMCGbxiq9hjntcuQ2uSWRBlz Qa5hU2kqqHbrkfaK7FD9DGDRfttjJLgkwih0YW7Fm4w1cdB9CAsoWtfeXi6dA+oZ1vbKnsGXz3c ZG5j6t+2y+KB5qDfK1I6RMB/v4bcOi50VBTwapynGcEufOtIF6o02zcaq30N+9hnSvAwfR4+tsx 6ryK/B2D/VG5jN/zfo2w= X-Google-Smtp-Source: AGHT+IH9IeGifKvkXgiFjBYh3A6bk6CTM/xn2kBB7e7GEVclWumFSaUXMg4bppH4WkqMdjRlk/Gmhw== X-Received: by 2002:a17:907:3e92:b0:acb:beb:e5df with SMTP id a640c23a62f3a-acb74745ea4mr348820066b.0.1745273219950; Mon, 21 Apr 2025 15:06: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 a640c23a62f3a-acbb8d49fdasm80311666b.67.2025.04.21.15.06.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 21 Apr 2025 15:06: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 v7 05/11] iio: accel: adxl345: add freefall feature Date: Mon, 21 Apr 2025 22:06:35 +0000 Message-Id: <20250421220641.105567-6-l.rubusch@gmail.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250421220641.105567-1-l.rubusch@gmail.com> References: <20250421220641.105567-1-l.rubusch@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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 | 134 +++++++++++++++++++++++++++++++ 1 file changed, 134 insertions(+) diff --git a/drivers/iio/accel/adxl345_core.c b/drivers/iio/accel/adxl345_c= ore.c index c464c87033fb..f42c861100cd 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; =20 __le16 fifo_buf[ADXL345_DIRS * ADXL345_FIFO_SIZE + 1] __aligned(IIO_DMA_M= INALIGN); }; @@ -122,10 +123,27 @@ enum adxl345_chans { chan_x, chan_y, chan_z, }; =20 +/* free fall */ +static const struct iio_event_spec adxl345_freefall_event_spec =3D { + .type =3D IIO_EV_TYPE_MAG, + .dir =3D IIO_EV_DIR_FALLING, + .mask_separate =3D BIT(IIO_EV_INFO_ENABLE), + .mask_shared_by_type =3D BIT(IIO_EV_INFO_VALUE) | + BIT(IIO_EV_INFO_PERIOD), +}; + static const struct iio_chan_spec adxl345_channels[] =3D { ADXL345_CHANNEL(0, chan_x, X), ADXL345_CHANNEL(1, chan_y, Y), ADXL345_CHANNEL(2, chan_z, Z), + { + .type =3D IIO_ACCEL, + .modified =3D 1, + .channel2 =3D IIO_MOD_X_AND_Y_AND_Z, + .scan_index =3D -1, /* Fake channel */ + .event_spec =3D &adxl345_freefall_event_spec, + .num_event_specs =3D 1, + }, }; =20 static const unsigned long adxl345_scan_masks[] =3D { @@ -383,6 +401,63 @@ 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); } =20 +/* freefall */ + +static int adxl345_is_ff_en(struct adxl345_state *st, bool *en) +{ + int ret; + unsigned int regval; + + ret =3D regmap_read(st->regmap, ADXL345_REG_INT_ENABLE, ®val); + if (ret) + return ret; + + *en =3D 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; + bool en; + int ret; + + ret =3D regmap_read(st->regmap, ADXL345_REG_THRESH_FF, &ff_threshold); + if (ret) + return ret; + + en =3D cmd_en && ff_threshold > 0 && st->ff_time_ms > 0; + + regval =3D en ? ADXL345_INT_FREE_FALL : 0x00; + + return regmap_update_bits(st->regmap, ADXL345_REG_INT_ENABLE, + ADXL345_INT_FREE_FALL, 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 =3D 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 =3D val_int * 1000 + DIV_ROUND_UP(val_fract_us, 1000); + st->ff_time_ms =3D val_ms; + + regval =3D 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) @@ -495,6 +570,11 @@ static int adxl345_read_event_config(struct iio_dev *i= ndio_dev, default: return -EINVAL; } + case IIO_EV_TYPE_MAG: + ret =3D adxl345_is_ff_en(st, &int_en); + if (ret) + return ret; + return int_en; default: return -EINVAL; } @@ -518,6 +598,8 @@ static int adxl345_write_event_config(struct iio_dev *i= ndio_dev, default: return -EINVAL; } + case IIO_EV_TYPE_MAG: + return adxl345_set_ff_en(st, state); default: return -EINVAL; } @@ -532,6 +614,7 @@ static int adxl345_read_event_value(struct iio_dev *ind= io_dev, { struct adxl345_state *st =3D iio_priv(indio_dev); unsigned int tap_threshold; + unsigned int ff_threshold; int ret; =20 switch (type) { @@ -565,6 +648,22 @@ static int adxl345_read_event_value(struct iio_dev *in= dio_dev, default: return -EINVAL; } + case IIO_EV_TYPE_MAG: + switch (info) { + case IIO_EV_INFO_VALUE: + ret =3D regmap_read(st->regmap, ADXL345_REG_THRESH_FF, + &ff_threshold); + if (ret) + return ret; + *val =3D ff_threshold; + return IIO_VAL_INT; + case IIO_EV_INFO_PERIOD: + *val =3D st->ff_time_ms; + *val2 =3D 1000; + return IIO_VAL_FRACTIONAL; + default: + return -EINVAL; + } default: return -EINVAL; } @@ -612,6 +711,22 @@ static int adxl345_write_event_value(struct iio_dev *i= ndio_dev, return -EINVAL; } break; + case IIO_EV_TYPE_MAG: + switch (info) { + case IIO_EV_INFO_VALUE: + ret =3D regmap_write(st->regmap, ADXL345_REG_THRESH_FF, val); + if (ret) + return ret; + break; + case IIO_EV_INFO_PERIOD: + ret =3D adxl345_set_ff_time(st, val, val2); + if (ret) + return ret; + break; + default: + return -EINVAL; + } + break; default: return -EINVAL; } @@ -865,6 +980,17 @@ static int adxl345_push_event(struct iio_dev *indio_de= v, int int_stat, return ret; } =20 + if (FIELD_GET(ADXL345_INT_FREE_FALL, int_stat)) { + ret =3D iio_push_event(indio_dev, + IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, + IIO_MOD_X_AND_Y_AND_Z, + IIO_EV_TYPE_MAG, + IIO_EV_DIR_FALLING), + ts); + if (ret) + return ret; + } + if (FIELD_GET(ADXL345_INT_WATERMARK, int_stat)) { samples =3D adxl345_get_samples(st); if (samples < 0) @@ -973,6 +1099,7 @@ int adxl345_core_probe(struct device *dev, struct regm= ap *regmap, ADXL345_DATA_FORMAT_FULL_RES | ADXL345_DATA_FORMAT_SELF_TEST); unsigned int tap_threshold; + unsigned int ff_threshold; int ret; =20 indio_dev =3D devm_iio_device_alloc(dev, sizeof(*st)); @@ -992,6 +1119,9 @@ int adxl345_core_probe(struct device *dev, struct regm= ap *regmap, st->tap_window_us =3D 64; /* 64 [0x40] -> .080 */ st->tap_latent_us =3D 16; /* 16 [0x10] -> .020 */ =20 + ff_threshold =3D 8; /* 8 [0x08] */ + st->ff_time_ms =3D 32; /* 32 [0x20] -> 0.16 */ + indio_dev->name =3D st->info->name; indio_dev->info =3D &adxl345_info; indio_dev->modes =3D INDIO_DIRECT_MODE; @@ -1068,6 +1198,10 @@ int adxl345_core_probe(struct device *dev, struct re= gmap *regmap, if (ret) return ret; =20 + ret =3D regmap_write(st->regmap, ADXL345_REG_THRESH_FF, ff_threshold); + if (ret) + return ret; + /* FIFO_STREAM mode is going to be activated later */ ret =3D devm_iio_kfifo_buffer_setup(dev, indio_dev, &adxl345_buffer_ops); if (ret) --=20 2.39.5 From nobody Tue Dec 16 21:01:36 2025 Received: from mail-ej1-f44.google.com (mail-ej1-f44.google.com [209.85.218.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 D217B221FB5; Mon, 21 Apr 2025 22:07:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.44 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1745273224; cv=none; b=oYM4ifCWAWePTMztWtDObnGKzsr0UH5un5yIrrY34lOr7DWxhg9UhVLaJ0FbmxLyC6OiTSHoQJFijnsf68cMQR2XfVrQU7qmNhNDwx7PvUOfZxhwTwvzyqV0D8twNPFTzLWnrH9gRszoBbT9NLeSLvRTfxuHVo1dZyFxLYMPvFY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1745273224; c=relaxed/simple; bh=98aSFRuIai1zdN24TsddkBKPbh6K9Efhft0eKZwYV38=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=Vm/1sYydY8cSU8R1IbaKlwYjbc1d/C9t80AqD0GkC38OK5XkfpXmjjz6gR3rINFzPoGL+VtGeYSDkjNEDN27TOJ5hdvO5UXcO3Rn5ACg10OGXfevLQQwGpjhcksD+YwwFYAX3JNimhZHZ0Bf5OjuRbypfIQ49H3RBfaZcxfJCDg= 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=WhMXA5u7; arc=none smtp.client-ip=209.85.218.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="WhMXA5u7" Received: by mail-ej1-f44.google.com with SMTP id a640c23a62f3a-acba3f5868eso17915466b.1; Mon, 21 Apr 2025 15:07:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1745273221; x=1745878021; 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=stjeSv+bIKrTRcusbfwsDYwsujSG2MwGqMzLbZEAMuw=; b=WhMXA5u71yhYj48Zs+MQ/txu8ofTcf8LmB7Y5HEqbMDPU0tAiSY96VjGUlSeleD8d0 n2GHXBPe8JZ9+oo0DkAzJX5EFOzme0I8EJjezeVLiZZsjmRb7JWTzTiV6yfGUdsc+k06 zs2gl6vaaC6xWMBFAJ9M+feaMrI0CTmmA2W2r5ED1LbvR1CIiI7aYHyQyoWZTU1HszdY MwbS5S6i0cXjs6F5R0WlrAPLc21a9LELmnJOQqqIfTOKOg521zJv6KSfo3F0vorRzcWW FNPLBRNI1IjIEhRAUQPxRW4K+nChXaUSA/kFQWJpDD8bua0Y4sjJ8KyQCokwsqO7hJzS oV8w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1745273221; x=1745878021; 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=stjeSv+bIKrTRcusbfwsDYwsujSG2MwGqMzLbZEAMuw=; b=oAtGZdF6my7uE0+z7fbu6lm6fBADd1/gy38J6wGC5eBwHg/4ykCla+PZHc5LbvzcaJ /b9C1/cnoQK7CxBwtz5YLfdy1vwO/TOkG71PmirAEQUTBQVfZhSGcnBik/w0u2HwwQMt ltT0Oj4cG/AnnDkyFARFm4z9yHVj0CZCsGToCvof37MN5Np2BxHXhkcfTlWhKEuVj7AW iEbJmYSSVxntC9c7pmRYTIFyojlVx8AVG3KBxqvHoYlQT+aQyQb4A513HpUKjiiy4CsG F1Qg3TBKZW94YnCgk5cYgH6oblxEP1anOchMwVN/DL/hBs5PtQbU/SJI85odDvIBLsU9 Xexg== X-Forwarded-Encrypted: i=1; AJvYcCWZsCR+Gb2wh9Ke1/9JKKOEWY5v65Vd3Ydb1M1YgJOdgg958hJFM4yFzz4SMusEYPlQbNlwhA7Gd7+t5WY=@vger.kernel.org X-Gm-Message-State: AOJu0YzKdBnJWnT8urzifs5CzdKW6JuZFOJln/ORAIvPyX4P9E4+qDXt VOYWyVnBGsql7KRHJyNesymWGyLui+4AaClSmf9WJf+7dGETDo9k X-Gm-Gg: ASbGncvydXiuaJNWY6VQ+JMd7hOqOW/8ft3yGQ+CJTvFIc9JfmVa0AA7iyCxSwA/iFy VA+AXXI5nGdhMRm2uRDCkSB/Xqp7bQdAVFTG29rcUF5MSuRNXlVtMNw19G9SCh2C9nwb415gMxj aaDEctjQxS4XDMSXf6V8DEGZs7E6tS9j/SQCEqMlqpQhD5rKtJsjGwTqDaFR2tnYDsUmZDp7RCd x5Us2jb0Z0YjC7P6YxNPNb6eTT/K/GgciaqZj0lezd8fh53p7H2+TQD/WQlnzsKsvZJkJH7xS5v ItElKrE2z8EYQPzW/wvmASjy4sF5Um2oZdsWeHSNDJot3VdxLQnyG994oRq3M/yF+XrJxeOlOlZ aCP5HtZqC0mTV4mLQvNs= X-Google-Smtp-Source: AGHT+IHJ+/LrdriPOjnip6Vxig9V9tRIs83pf6duEYGUGecYxAY8wGsyMTfoT2vj0iHJOSUVfvqLpg== X-Received: by 2002:a17:907:3e9f:b0:acb:6337:4923 with SMTP id a640c23a62f3a-acb74d85650mr388898666b.11.1745273220886; Mon, 21 Apr 2025 15:07:00 -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 a640c23a62f3a-acbb8d49fdasm80311666b.67.2025.04.21.15.07.00 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 21 Apr 2025 15:07: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 v7 06/11] iio: accel: adxl345: extend sample frequency adjustments Date: Mon, 21 Apr 2025 22:06:36 +0000 Message-Id: <20250421220641.105567-7-l.rubusch@gmail.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250421220641.105567-1-l.rubusch@gmail.com> References: <20250421220641.105567-1-l.rubusch@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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 =20 diff --git a/drivers/iio/accel/adxl345_core.c b/drivers/iio/accel/adxl345_c= ore.c index f42c861100cd..7ed7ee3a8358 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[] =3D { [ADXL345_TAP_TIME_DUR] =3D ADXL345_REG_DUR, }; =20 +enum adxl345_odr { + ADXL345_ODR_0P10HZ =3D 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] =3D { + [ADXL345_ODR_0P10HZ] =3D { 0, 97000 }, + [ADXL345_ODR_0P20HZ] =3D { 0, 195000 }, + [ADXL345_ODR_0P39HZ] =3D { 0, 390000 }, + [ADXL345_ODR_0P78HZ] =3D { 0, 781000 }, + [ADXL345_ODR_1P56HZ] =3D { 1, 562000 }, + [ADXL345_ODR_3P13HZ] =3D { 3, 125000 }, + [ADXL345_ODR_6P25HZ] =3D { 6, 250000 }, + [ADXL345_ODR_12P50HZ] =3D { 12, 500000 }, + [ADXL345_ODR_25HZ] =3D { 25, 0 }, + [ADXL345_ODR_50HZ] =3D { 50, 0 }, + [ADXL345_ODR_100HZ] =3D { 100, 0 }, + [ADXL345_ODR_200HZ] =3D { 200, 0 }, + [ADXL345_ODR_400HZ] =3D { 400, 0 }, + [ADXL345_ODR_800HZ] =3D { 800, 0 }, + [ADXL345_ODR_1600HZ] =3D { 1600, 0 }, + [ADXL345_ODR_3200HZ] =3D { 3200, 0 }, +}; + struct adxl345_state { const struct adxl345_chip_info *info; struct regmap *regmap; @@ -108,6 +147,7 @@ static struct iio_event_spec adxl345_events[] =3D { BIT(IIO_CHAN_INFO_CALIBBIAS), \ .info_mask_shared_by_type =3D BIT(IIO_CHAN_INFO_SCALE) | \ BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .info_mask_shared_by_type_available =3D BIT(IIO_CHAN_INFO_SAMP_FREQ), \ .scan_index =3D (index), \ .scan_type =3D { \ .sign =3D 's', \ @@ -458,14 +498,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)); } =20 +static int adxl345_find_odr(struct adxl345_state *st, int val, + int val2, enum adxl345_odr *odr) +{ + int i; + + for (i =3D 0; i < ARRAY_SIZE(adxl345_odr_tbl); i++) { + if (val =3D=3D adxl345_odr_tbl[i][0] && + val2 =3D=3D adxl345_odr_tbl[i][1]) { + *odr =3D 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 =3D (int *)adxl345_odr_tbl; + *type =3D IIO_VAL_INT_PLUS_MICRO; + *length =3D 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 =3D iio_priv(indio_dev); __le16 accel; - long long samp_freq_nhz; unsigned int regval; + enum adxl345_odr odr; int ret; =20 switch (mask) { @@ -503,12 +582,10 @@ static int adxl345_read_raw(struct iio_dev *indio_dev, ret =3D regmap_read(st->regmap, ADXL345_REG_BW_RATE, ®val); if (ret) return ret; - - samp_freq_nhz =3D ADXL345_BASE_RATE_NANO_HZ << - (regval & ADXL345_BW_RATE); - *val =3D div_s64_rem(samp_freq_nhz, NANOHZ_PER_HZ, val2); - - return IIO_VAL_INT_PLUS_NANO; + odr =3D FIELD_GET(ADXL345_BW_RATE_MSK, regval); + *val =3D adxl345_odr_tbl[odr][0]; + *val2 =3D adxl345_odr_tbl[odr][1]; + return IIO_VAL_INT_PLUS_MICRO; } =20 return -EINVAL; @@ -519,7 +596,12 @@ static int adxl345_write_raw(struct iio_dev *indio_dev, int val, int val2, long mask) { struct adxl345_state *st =3D iio_priv(indio_dev); - s64 n; + enum adxl345_odr odr; + int ret; + + ret =3D adxl345_set_measure_en(st, false); + if (ret) + return ret; =20 switch (mask) { case IIO_CHAN_INFO_CALIBBIAS: @@ -527,20 +609,26 @@ static int adxl345_write_raw(struct iio_dev *indio_de= v, * 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 =3D regmap_write(st->regmap, + ADXL345_REG_OFS_AXIS(chan->address), + val / 4); + if (ret) + return ret; + break; case IIO_CHAN_INFO_SAMP_FREQ: - n =3D div_s64(val * NANOHZ_PER_HZ + val2, - ADXL345_BASE_RATE_NANO_HZ); + ret =3D adxl345_find_odr(st, val, val2, &odr); + if (ret) + return ret; =20 - return regmap_update_bits(st->regmap, ADXL345_REG_BW_RATE, - ADXL345_BW_RATE, - clamp_val(ilog2(n), 0, - ADXL345_BW_RATE)); + ret =3D adxl345_set_odr(st, odr); + if (ret) + return ret; + break; + default: + return -EINVAL; } =20 - return -EINVAL; + return adxl345_set_measure_en(st, true); } =20 static int adxl345_read_event_config(struct iio_dev *indio_dev, @@ -769,7 +857,7 @@ static int adxl345_write_raw_get_fmt(struct iio_dev *in= dio_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; } @@ -782,19 +870,6 @@ static void adxl345_powerdown(void *ptr) adxl345_set_measure_en(st, false); } =20 -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 20= 0 400 800 1600 3200" -); - -static struct attribute *adxl345_attrs[] =3D { - &iio_const_attr_sampling_frequency_available.dev_attr.attr, - NULL -}; - -static const struct attribute_group adxl345_attrs_group =3D { - .attrs =3D adxl345_attrs, -}; - static int adxl345_set_fifo(struct adxl345_state *st) { unsigned int intio; @@ -1057,9 +1132,9 @@ static irqreturn_t adxl345_irq_handler(int irq, void = *p) } =20 static const struct iio_info adxl345_info =3D { - .attrs =3D &adxl345_attrs_group, .read_raw =3D adxl345_read_raw, .write_raw =3D adxl345_write_raw, + .read_avail =3D adxl345_read_avail, .write_raw_get_fmt =3D adxl345_write_raw_get_fmt, .read_event_config =3D adxl345_read_event_config, .write_event_config =3D adxl345_write_event_config, @@ -1129,6 +1204,15 @@ int adxl345_core_probe(struct device *dev, struct re= gmap *regmap, indio_dev->num_channels =3D ARRAY_SIZE(adxl345_channels); indio_dev->available_scan_masks =3D adxl345_scan_masks; =20 + /* + * 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 =3D adxl345_set_odr(st, ADXL345_ODR_200HZ); + if (ret) + return ret; + /* Reset interrupts at start up */ ret =3D regmap_write(st->regmap, ADXL345_REG_INT_ENABLE, 0x00); if (ret) --=20 2.39.5 From nobody Tue Dec 16 21:01:36 2025 Received: from mail-ed1-f47.google.com (mail-ed1-f47.google.com [209.85.208.47]) (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 EBC67221FDD; Mon, 21 Apr 2025 22:07:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.47 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1745273225; cv=none; b=EjqP18ea4TG0MOuu3TJqr/CxCyBN4mGGy76lddExDVsNmFErw9e38Za/0OSYIKUe5FZ1FXtyuI8KLbgpK85E3WZL6q+DJLVryv64Rev+vDIfDMc8pgZvIX3kg9HX0X0aLTrrFtG3xpixHOs0cbX++VF2wmChE3J/t+clP5C9+4Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1745273225; c=relaxed/simple; bh=/OqPkoBfWAuKwsYLkvJU1u0zHSE9W1kE7j7734XlkpU=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=V5irA50s70HXKUv0VNoyMyAXIsySq9CAE5x4+UUHgpq0lV3StGdBnNVkyoGnfShxqM+OX2SFuU08wd9YhFYKDOlf9erOopDhUgWYhWR/lFMU7mlyo4DJATO7kDWcPWfSC1oPpmMn4A1Kke8yk3WbU+RfeSV5olrIBjXSGxD0p4I= 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=lw0yForE; arc=none smtp.client-ip=209.85.208.47 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="lw0yForE" Received: by mail-ed1-f47.google.com with SMTP id 4fb4d7f45d1cf-5e8484bb895so1324489a12.0; Mon, 21 Apr 2025 15:07:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1745273222; x=1745878022; 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=5b626K7Nkaf57agQTokJNBDI19D5VPDm/uav8QnS+kc=; b=lw0yForEZE7kDdGnuC5lCtBc2ZL8pw6/cxlo20theot0slbwWagKu8iI/37b4KyFa1 PjDG8/bOrUw91ID5WFZfOaEKei8SadKiiQIWFq+/o+aVMekJ9Wdmmk12YapOARP0J/2t aq/XJLEY67IYkmhQm7SOBhmuB6didDpaVRN1xz0V0fuV9F3jyFqgCdVoQzzoFMrtGpVE j3PgEqYOXek+USlspiPDxlKw1+Uq5NB2ugvim7kQhJXc2F/dZXHRvEmIsw9GCiZhr145 lgiKgdTgNVxCa8UYupHJ+zHTB/kwOP1uJ8OHQzu/Wf4EIBDID5XI1T0+EU1DAoecHApk hGUA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1745273222; x=1745878022; 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=5b626K7Nkaf57agQTokJNBDI19D5VPDm/uav8QnS+kc=; b=XIUuw60THbH7TWXV+2FLuhcJqiVp3mXgLoAt9PgzL1t6Hq0jcRYbGQjRVplbLNCtdC cGJXePzd0XIgPMSA1WkPMGCEup2nj70Yc5puPLaSpcWlCbUqdGUmtcB/jDfzsJ+Da2j9 13oTcHIGyXZRCG5hRVCejecdT+MHARQ9p0LdV+1RqN95BWbv5JNtDPDxtgkB2669fZ13 Hz9NrirCyd9tK/g4XXLCU7m0ChQg4XvY/kCVzxGyx3YghhoNTPcTm/AT5d8I1QtHjayH fvWHWq+29uVbGV5CMYndGVXgLarCcRaMmmmy/+xiCBcnyhAuAkKCCX6IOyIsA7vF1PNR Nf8A== X-Forwarded-Encrypted: i=1; AJvYcCVOB7B4prj+FmEDq8Vnyees18WlTA/KvsUmq1PSaydYVnnTFA/DqqRMEMMyPFMo3LDl5IO72iHGWM1d1ao=@vger.kernel.org X-Gm-Message-State: AOJu0YyZ/AZ5pX8OWDordtVs38i0U/jWKkbVUZVuXrYsguek5kDkSxci 1sTT5wwevNQfGenLp6ND0nlAECRTnoOPodNdFh/Us3T5IqY4hpe7 X-Gm-Gg: ASbGncsEY7mTdqvaSrFNk2bBDEPp1vMYa/VFjsfnwMGDEQIgNwI+7z/M9bw0XG1j4I+ HAGXkco4uI3fAe/jd2+l4szUXUNtTHNewrjEK+hn+DaDgCS/XjgPorfuFZCCzIA6FjW7mhta86d neLQUY1KysybC9L4Y3rTOfKSMTxqsIGGzGKhuOMtlPfe9nXKjcBPml+GIP/xigz2qnla9cB/kuG 5vijr9gBsIwBgujU0Mabjh5/iwmr9NC9fmQAzCNS5LSeswbcuuPJ2Lq+lR4MkepLgDa5Co8Mmn/ w+V2D403EPK8+z9eK2/joNx03G12dQNp0heMkrR7S8IShpX7nBcP47wT7s43Z7rkjnEE8jKgfA4 5wLvPRqfo/6aXpn8TCb0= X-Google-Smtp-Source: AGHT+IHEakMIAi6eU5Rae9hTCUTZmtPZyVrg59D9PJXber6SHIEQKdo3XxxLoK7WUTWcshotcL0gkA== X-Received: by 2002:a17:907:7f0d:b0:acb:583:c63a with SMTP id a640c23a62f3a-acb74dd060cmr337215566b.15.1745273221952; Mon, 21 Apr 2025 15:07: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 a640c23a62f3a-acbb8d49fdasm80311666b.67.2025.04.21.15.07.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 21 Apr 2025 15:07: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 v7 07/11] iio: accel: adxl345: add g-range configuration Date: Mon, 21 Apr 2025 22:06:37 +0000 Message-Id: <20250421220641.105567-8-l.rubusch@gmail.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250421220641.105567-1-l.rubusch@gmail.com> References: <20250421220641.105567-1-l.rubusch@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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_c= ore.c index 7ed7ee3a8358..80b5b8402ced 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, }; =20 +enum adxl345_range { + ADXL345_2G_RANGE =3D 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] =3D { [ADXL345_ODR_0P10HZ] =3D { 0, 97000 }, @@ -103,6 +110,33 @@ static const int adxl345_odr_tbl[][2] =3D { [ADXL345_ODR_3200HZ] =3D { 3200, 0 }, }; =20 +/* + * Full resolution frequency table: + * (g * 2 * 9.80665) / (2^(resolution) - 1) + * + * resolution :=3D 13 (full) + * g :=3D 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] =3D { + [ADXL345_2G_RANGE] =3D { 0, 4789 }, + [ADXL345_4G_RANGE] =3D { 0, 9578 }, + [ADXL345_8G_RANGE] =3D { 0, 19156 }, + [ADXL345_16G_RANGE] =3D { 0, 38312 }, +}; + +/* scaling */ +static const int adxl345_range_factor_tbl[] =3D { + [ADXL345_2G_RANGE] =3D 1, + [ADXL345_4G_RANGE] =3D 2, + [ADXL345_8G_RANGE] =3D 4, + [ADXL345_16G_RANGE] =3D 8, +}; + struct adxl345_state { const struct adxl345_chip_info *info; struct regmap *regmap; @@ -147,7 +181,8 @@ static struct iio_event_spec adxl345_events[] =3D { BIT(IIO_CHAN_INFO_CALIBBIAS), \ .info_mask_shared_by_type =3D BIT(IIO_CHAN_INFO_SCALE) | \ BIT(IIO_CHAN_INFO_SAMP_FREQ), \ - .info_mask_shared_by_type_available =3D BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .info_mask_shared_by_type_available =3D BIT(IIO_CHAN_INFO_SCALE) | \ + BIT(IIO_CHAN_INFO_SAMP_FREQ), \ .scan_index =3D (index), \ .scan_type =3D { \ .sign =3D 's', \ @@ -521,12 +556,40 @@ static int adxl345_set_odr(struct adxl345_state *st, = enum adxl345_odr odr) FIELD_PREP(ADXL345_BW_RATE_MSK, odr)); } =20 +static int adxl345_find_range(struct adxl345_state *st, int val, int val2, + enum adxl345_range *range) +{ + int i; + + for (i =3D 0; i < ARRAY_SIZE(adxl345_fullres_range_tbl); i++) { + if (val =3D=3D adxl345_fullres_range_tbl[i][0] && + val2 =3D=3D adxl345_fullres_range_tbl[i][1]) { + *range =3D 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 =3D (int *)adxl345_fullres_range_tbl; + *type =3D IIO_VAL_INT_PLUS_MICRO; + *length =3D ARRAY_SIZE(adxl345_fullres_range_tbl) * 2; + return IIO_AVAIL_LIST; case IIO_CHAN_INFO_SAMP_FREQ: *vals =3D (int *)adxl345_odr_tbl; *type =3D IIO_VAL_INT_PLUS_MICRO; @@ -545,6 +608,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; =20 switch (mask) { @@ -563,8 +627,12 @@ static int adxl345_read_raw(struct iio_dev *indio_dev, *val =3D sign_extend32(le16_to_cpu(accel), 12); return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: - *val =3D 0; - *val2 =3D st->info->uscale; + ret =3D regmap_read(st->regmap, ADXL345_REG_DATA_FORMAT, ®val); + if (ret) + return ret; + range =3D FIELD_GET(ADXL345_DATA_FORMAT_RANGE, regval); + *val =3D adxl345_fullres_range_tbl[range][0]; + *val2 =3D adxl345_fullres_range_tbl[range][1]; return IIO_VAL_INT_PLUS_MICRO; case IIO_CHAN_INFO_CALIBBIAS: ret =3D regmap_read(st->regmap, @@ -596,6 +664,7 @@ static int adxl345_write_raw(struct iio_dev *indio_dev, int val, int val2, long mask) { struct adxl345_state *st =3D iio_priv(indio_dev); + enum adxl345_range range; enum adxl345_odr odr; int ret; =20 @@ -624,6 +693,15 @@ static int adxl345_write_raw(struct iio_dev *indio_dev, if (ret) return ret; break; + case IIO_CHAN_INFO_SCALE: + ret =3D adxl345_find_range(st, val, val2, &range); + if (ret) + return ret; + + ret =3D adxl345_set_range(st, range); + if (ret) + return ret; + break; default: return -EINVAL; } @@ -856,6 +934,8 @@ static int adxl345_write_raw_get_fmt(struct iio_dev *in= dio_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: @@ -1213,6 +1293,10 @@ int adxl345_core_probe(struct device *dev, struct re= gmap *regmap, if (ret) return ret; =20 + ret =3D adxl345_set_range(st, ADXL345_16G_RANGE); + if (ret) + return ret; + /* Reset interrupts at start up */ ret =3D regmap_write(st->regmap, ADXL345_REG_INT_ENABLE, 0x00); if (ret) --=20 2.39.5 From nobody Tue Dec 16 21:01:36 2025 Received: from mail-ed1-f45.google.com (mail-ed1-f45.google.com [209.85.208.45]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0BF5F2236E4; Mon, 21 Apr 2025 22:07:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.45 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1745273227; cv=none; b=PDAVcb/N+pwHQ7Dn/GTZEI+qiiV6LHbkTpwreVu6HiQnTdCwLfDOjmKj8IH5RdXSyRXHdK0tCMVSzLX3xtJ6+HSnT7SBucnsOUGhmvHQAFbr98g/cquzbMX6F/i+E8OCFKOnH9rUfv2Gy0qZHORPB+T2raeXg+cyivqfruQXstk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1745273227; c=relaxed/simple; bh=EtD3rmJf7q/N/LrJ8EPBuCdxDjFFCbLFEV4iJjPxgVA=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=b9eBjQAsrwQBP+4HhI7nYdnxcPd41WW3wtvvhmylmv1P74eZ1cFCH7zzCPRECzUs4/JczOVLpzM1w8XUhqPHnaoN454Mg+lh53uLhWDxyiULfhYSp+oML3JQHYLAvsYnbd1b3WXaqTCfVFuOeK5B6JOMUcwP/Mrtp06Zq/VPQA0= 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=GNj6u4nU; arc=none smtp.client-ip=209.85.208.45 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="GNj6u4nU" Received: by mail-ed1-f45.google.com with SMTP id 4fb4d7f45d1cf-5e61a18c05aso649817a12.1; Mon, 21 Apr 2025 15:07:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1745273223; x=1745878023; 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=uhhH8vW1ua9waxt1NFmM81BM9/bkLnKgIhzCXzZVw7Q=; b=GNj6u4nUT+uAMbMjL6U3lF6yXLIFQpbQuXeNqiW6op2VrdR+s6qWbwJxHeW44Q916R idL/dNf9/RrBcUMSl8AY+QQaA6d6sdvKA2Mxu30vrnjFhBycqHE56CAbGB+v8wf84Z4c AC25BQwAeugkyf9AOfUP48SbY38EmSb4woH+WbvBqReBYrsktBvLWYkoSOu7jeB9SAke 5gkd96spmk1+A3goy+/Xuiem5GYMH9fG4/zWcxKYvWGrDBDfujInaEuQfh6z1Fp+qIp0 Ko21OuLmmAx1nimO+lH11VT6ObzjsWpVLh+uq8OAV0wMl8k2a6JufO//to5P0HVKHf/0 d8Ow== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1745273223; x=1745878023; 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=uhhH8vW1ua9waxt1NFmM81BM9/bkLnKgIhzCXzZVw7Q=; b=L06nI16l6tP6+JFicxlh3uOWSSYIXIPU/F5cdcIpZjIH/kLSPxMURIunGBvVchJsYf ThQxwxqyUS0WEKYksg0b3WfoNQb376s/rrJrFqCNnq/zFVftZqB+Vj89u6rc5JYZJ0fe r9mT1p1KI6cpPvx8topxlPDZf3tVcvynAhYJhIF4dYOddr/4fOgVP54RaopDiz9l2TH6 XolEJK9rTW4USmqqQoS+tKDCB3M4SZkJnXOH3ILLFHgENi632wkvv0rAM2emBA+D8oJC MA0RbrbTRlRttJokUiilpqVJCNgz/vMpuiztOQt6+l/DI0byc95m0ozgflaJmSeYx2ov hLxw== X-Forwarded-Encrypted: i=1; AJvYcCVBuJOxQAIgRaEoGhVunTRYXiJBXztxlNXBM5hW0uCz7cPtN2xOKvBlClqEjYPb3Xkxs6WUg8MTImtIU7A=@vger.kernel.org X-Gm-Message-State: AOJu0YyaDmbkjcVl9vup1kl3wfrOS3TXin7t27LosZ8Ba+4WGMB7A3d9 dHDNh9rW5q5jYj22ZFfp4jI+cZF1Zwjeo+gaZQaLUdRxtrlNzeP3 X-Gm-Gg: ASbGncvF2xAVbBpnj8Qly7M8tMrbFVusYu93TrWwmRqRqHP1bX4bK8nbl0VM07QLO37 /pxI8zM6VfwFcVW+tYP2sb8vHzSJCBjjeSpew77NyjXCeeWBGyNb6MIltyTK7mMX1d6oyoX8wae u5+434s7wCROU8rejivnAMBRjH8tqp/QadVOePImhLIY7BfOIjDwudcrGf5NEx1NvqPqYVClL4S 2rQ/y10qxe2fXr5DelNRNmZf186eeD7TyXJNd/QDX9Lcqei2vVRakjLNjpvN7AoeV91H709QzTg HmfQAYaXdrlvlwHhCLQFKqCOhQmChAEJVq/Lg1rA6s6rLQlIkELa1qEA//3DE9WWz3E7CKed6aG e6PhtFaZGoozyqD4nNpc= X-Google-Smtp-Source: AGHT+IG14W9Vc5Sfxpctf5Tz5utDxHpICMMmU4pPCOkAt/tAD65UkiENCpe2R7ADOCJUf+eV9Ppo7w== X-Received: by 2002:a17:907:7f0d:b0:acb:583:c63a with SMTP id a640c23a62f3a-acb74dd060cmr337217266b.15.1745273223012; Mon, 21 Apr 2025 15:07: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 a640c23a62f3a-acbb8d49fdasm80311666b.67.2025.04.21.15.07.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 21 Apr 2025 15:07:02 -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 v7 08/11] iio: accel: adxl345: add activity event feature Date: Mon, 21 Apr 2025 22:06:38 +0000 Message-Id: <20250421220641.105567-9-l.rubusch@gmail.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250421220641.105567-1-l.rubusch@gmail.com> References: <20250421220641.105567-1-l.rubusch@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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 | 217 ++++++++++++++++++++++++++++++- 1 file changed, 214 insertions(+), 3 deletions(-) diff --git a/drivers/iio/accel/adxl345_core.c b/drivers/iio/accel/adxl345_c= ore.c index 80b5b8402ced..680981609d83 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) =20 #define ADXL345_TAP_Z_EN BIT(0) #define ADXL345_TAP_Y_EN BIT(1) #define ADXL345_TAP_X_EN BIT(2) =20 +#define ADXL345_ACT_Z_EN BIT(4) +#define ADXL345_ACT_Y_EN BIT(5) +#define ADXL345_ACT_X_EN BIT(6) + /* single/double tap */ enum adxl345_tap_type { ADXL345_SINGLE_TAP, @@ -64,6 +69,19 @@ static const unsigned int adxl345_tap_time_reg[] =3D { [ADXL345_TAP_TIME_DUR] =3D ADXL345_REG_DUR, }; =20 +/* activity/inactivity */ +enum adxl345_activity_type { + ADXL345_ACTIVITY, +}; + +static const unsigned int adxl345_act_int_reg[] =3D { + [ADXL345_ACTIVITY] =3D ADXL345_INT_ACTIVITY, +}; + +static const unsigned int adxl345_act_thresh_reg[] =3D { + [ADXL345_ACTIVITY] =3D ADXL345_REG_THRESH_ACT, +}; + enum adxl345_odr { ADXL345_ODR_0P10HZ =3D 0, ADXL345_ODR_0P20HZ, @@ -154,6 +172,13 @@ struct adxl345_state { }; =20 static struct iio_event_spec adxl345_events[] =3D { + { + /* activity */ + .type =3D IIO_EV_TYPE_THRESH, + .dir =3D IIO_EV_DIR_RISING, + .mask_separate =3D BIT(IIO_EV_INFO_ENABLE), + .mask_shared_by_type =3D BIT(IIO_EV_INFO_VALUE), + }, { /* single tap */ .type =3D IIO_EV_TYPE_GESTURE, @@ -265,6 +290,99 @@ static int adxl345_set_measure_en(struct adxl345_state= *st, bool en) return regmap_write(st->regmap, ADXL345_REG_POWER_CTL, val); } =20 +/* 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; + u32 axis_ctrl; + int ret; + + ret =3D regmap_read(st->regmap, ADXL345_REG_ACT_INACT_CTRL, &axis_ctrl); + if (ret) + return ret; + + if (type =3D=3D ADXL345_ACTIVITY) { + switch (axis) { + case IIO_MOD_X: + *en =3D FIELD_GET(ADXL345_ACT_X_EN, axis_ctrl); + break; + case IIO_MOD_Y: + *en =3D FIELD_GET(ADXL345_ACT_Y_EN, axis_ctrl); + break; + case IIO_MOD_Z: + *en =3D FIELD_GET(ADXL345_ACT_Z_EN, axis_ctrl); + break; + default: + *en =3D false; + return -EINVAL; + } + } + + if (*en) { + ret =3D regmap_read(st->regmap, ADXL345_REG_INT_ENABLE, ®val); + if (ret) + return ret; + + *en =3D adxl345_act_int_reg[type] & regval; + } + + 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 en; + unsigned int threshold; + u32 axis_ctrl =3D 0; + int ret; + + if (type =3D=3D ADXL345_ACTIVITY) { + switch (axis) { + case IIO_MOD_X: + axis_ctrl =3D ADXL345_ACT_X_EN; + break; + case IIO_MOD_Y: + axis_ctrl =3D ADXL345_ACT_Y_EN; + break; + case IIO_MOD_Z: + axis_ctrl =3D ADXL345_ACT_Z_EN; + break; + default: + return -EINVAL; + } + } + + if (cmd_en) + ret =3D regmap_set_bits(st->regmap, + ADXL345_REG_ACT_INACT_CTRL, axis_ctrl); + else + ret =3D regmap_clear_bits(st->regmap, + ADXL345_REG_ACT_INACT_CTRL, axis_ctrl); + if (ret) + return ret; + + ret =3D regmap_read(st->regmap, adxl345_act_thresh_reg[type], &threshold); + if (ret) + return ret; + + en =3D false; + + if (type =3D=3D ADXL345_ACTIVITY) { + en =3D FIELD_GET(ADXL345_REG_ACT_AXIS_MSK, axis_ctrl) && + threshold; + } + + return regmap_update_bits(st->regmap, ADXL345_REG_INT_ENABLE, + adxl345_act_int_reg[type], + en ? adxl345_act_int_reg[type] : 0); +} + /* tap */ =20 static int _adxl345_set_tap_int(struct adxl345_state *st, @@ -719,6 +837,18 @@ static int adxl345_read_event_config(struct iio_dev *i= ndio_dev, int ret; =20 switch (type) { + case IIO_EV_TYPE_THRESH: + switch (dir) { + case IIO_EV_DIR_RISING: + ret =3D 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: @@ -755,6 +885,14 @@ static int adxl345_write_event_config(struct iio_dev *= indio_dev, struct adxl345_state *st =3D iio_priv(indio_dev); =20 switch (type) { + case IIO_EV_TYPE_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: @@ -779,11 +917,31 @@ static int adxl345_read_event_value(struct iio_dev *i= ndio_dev, int *val, int *val2) { struct adxl345_state *st =3D iio_priv(indio_dev); + unsigned int act_threshold; unsigned int tap_threshold; unsigned int ff_threshold; int ret; =20 switch (type) { + case IIO_EV_TYPE_THRESH: + switch (info) { + case IIO_EV_INFO_VALUE: + switch (dir) { + case IIO_EV_DIR_RISING: + ret =3D regmap_read(st->regmap, + adxl345_act_thresh_reg[ADXL345_ACTIVITY], + &act_threshold); + if (ret) + return ret; + + *val =3D act_threshold; + return IIO_VAL_INT; + default: + return -EINVAL; + } + default: + return -EINVAL; + } case IIO_EV_TYPE_GESTURE: switch (info) { case IIO_EV_INFO_VALUE: @@ -850,6 +1008,25 @@ static int adxl345_write_event_value(struct iio_dev *= indio_dev, return ret; =20 switch (type) { + case IIO_EV_TYPE_THRESH: + switch (info) { + case IIO_EV_INFO_VALUE: + switch (dir) { + case IIO_EV_DIR_RISING: + ret =3D 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: @@ -1108,7 +1285,8 @@ static int adxl345_fifo_push(struct iio_dev *indio_de= v, } =20 static int adxl345_push_event(struct iio_dev *indio_dev, int int_stat, - enum iio_modifier tap_dir) + enum iio_modifier tap_dir, + enum iio_modifier act_dir) { s64 ts =3D iio_get_time_ns(indio_dev); struct adxl345_state *st =3D iio_priv(indio_dev); @@ -1135,6 +1313,16 @@ static int adxl345_push_event(struct iio_dev *indio_= dev, int int_stat, return ret; } =20 + if (FIELD_GET(ADXL345_INT_ACTIVITY, int_stat)) { + ret =3D iio_push_event(indio_dev, + IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, act_dir, + IIO_EV_TYPE_THRESH, + IIO_EV_DIR_RISING), + ts); + if (ret) + return ret; + } + if (FIELD_GET(ADXL345_INT_FREE_FALL, int_stat)) { ret =3D iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, @@ -1173,6 +1361,7 @@ static irqreturn_t adxl345_irq_handler(int irq, void = *p) struct adxl345_state *st =3D iio_priv(indio_dev); unsigned int regval; enum iio_modifier tap_dir =3D IIO_NO_MOD; + enum iio_modifier act_dir =3D IIO_NO_MOD; u32 axis_ctrl; int int_stat; int ret; @@ -1181,7 +1370,8 @@ static irqreturn_t adxl345_irq_handler(int irq, void = *p) if (ret) return IRQ_NONE; =20 - if (FIELD_GET(ADXL345_REG_TAP_AXIS_MSK, axis_ctrl)) { + if (FIELD_GET(ADXL345_REG_TAP_AXIS_MSK, axis_ctrl) || + FIELD_GET(ADXL345_REG_ACT_AXIS_MSK, axis_ctrl)) { ret =3D regmap_read(st->regmap, ADXL345_REG_ACT_TAP_STATUS, ®val); if (ret) return IRQ_NONE; @@ -1192,12 +1382,19 @@ static irqreturn_t adxl345_irq_handler(int irq, voi= d *p) tap_dir =3D IIO_MOD_Y; else if (FIELD_GET(ADXL345_TAP_X_EN, regval)) tap_dir =3D IIO_MOD_X; + + if (FIELD_GET(ADXL345_ACT_Z_EN, regval)) + act_dir =3D IIO_MOD_Z; + else if (FIELD_GET(ADXL345_ACT_Y_EN, regval)) + act_dir =3D IIO_MOD_Y; + else if (FIELD_GET(ADXL345_ACT_X_EN, regval)) + act_dir =3D IIO_MOD_X; } =20 if (regmap_read(st->regmap, ADXL345_REG_INT_SOURCE, &int_stat)) return IRQ_NONE; =20 - if (adxl345_push_event(indio_dev, int_stat, tap_dir)) + if (adxl345_push_event(indio_dev, int_stat, tap_dir, act_dir)) goto err; =20 if (FIELD_GET(ADXL345_INT_OVERRUN, int_stat)) @@ -1362,6 +1559,20 @@ int adxl345_core_probe(struct device *dev, struct re= gmap *regmap, if (ret) return ret; =20 + /* + * Initialization with reasonable values to simplify operation + * of the sensor. The default values are partly taken from the + * older input driver for the ADXL345, and partly based on + * recommendations in the datasheet. + */ + ret =3D regmap_write(st->regmap, ADXL345_REG_ACT_INACT_CTRL, 0); + if (ret) + return ret; + + ret =3D regmap_write(st->regmap, ADXL345_REG_THRESH_ACT, 6); + if (ret) + return ret; + ret =3D regmap_write(st->regmap, ADXL345_REG_THRESH_TAP, tap_threshold); if (ret) return ret; --=20 2.39.5 From nobody Tue Dec 16 21:01:36 2025 Received: from mail-ej1-f48.google.com (mail-ej1-f48.google.com [209.85.218.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 13A21224894; Mon, 21 Apr 2025 22:07:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.48 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1745273228; cv=none; b=jlLArs+Ew8BFEJSd/7IB5MQvO7ydBwGU63nRbVOyldEb9pCzMq9FwcBk+SE+IKquCh8BwCcePjvJJ6B9QD7V9ocanEeUkB6RqBjs5ECJDC6kf9J7AMi3CuR5bPchOpmPlRjwInyTGue6Db6JPL9Gaw5Db7hqXrRsjObLmn3692w= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1745273228; c=relaxed/simple; bh=mbcERdFQQom/BTOHUff26fkRFKWLbyOhAi5VHByJqTY=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=Eb1n38V9ry8J2UvdmWxE1E105f1zi5Z46LPH2r/5Kp/+IIAxwFBUjiUzTuJvi6vNX9lXqXz9maiw0tbmiBjvZxBoPlbezrf5NJY/95iQKW/hCV0MMTj6jVqPPBGHrPkxJ9wcwHYask8EYrQQB0CW38RrNZAEBCsLMnDI9ReM7k8= 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=HyEo4rQ2; arc=none smtp.client-ip=209.85.218.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="HyEo4rQ2" Received: by mail-ej1-f48.google.com with SMTP id a640c23a62f3a-ac30d4ee128so62869266b.0; Mon, 21 Apr 2025 15:07:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1745273224; x=1745878024; 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=wdu0LdDj62KC+oWS88znCzXV1CP0ELp5VSRb6zCbXT0=; b=HyEo4rQ2QwLvxfva5+bjLcP5m4NYYi4WaNiBI46qoiPO8MECNwl2H24XgvwqUtTb6M lRl5Ht3iHZvriTc0jgzUbCYhJIBBfChvRnXot7rMblyRlbryzizmhMEaCshOaDiRSHJY pilXNDBGnb5oofDOYCtDzuvnHSF8CfQ0dN97JG32PvwA3SMOFtZ/DgQaXfZSyANACVCD Rtg6P9Jefpf5DttvhQSPJzNk86Pj29cGaB3NVwdr8kUQYXHN0H8tCbrA4nEU983KwWz7 oFG+hr/QHPzRC1/yU367VCYjHBRw+lcnZju4ajwlzlgtpEuz1xZx2c9HNJMneJbcH0Xe qBUA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1745273224; x=1745878024; 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=wdu0LdDj62KC+oWS88znCzXV1CP0ELp5VSRb6zCbXT0=; b=wiL6XGCwMH1CCOJBJ5ojUiNNyPn6v3Rif2VwoVB2qajZ4bUz8kf5Fk0ygsebJUynoa +tHg88mys14xarCophE4bkHLmVoaUGdwHYEKzn5e+5yLr2rR/D1/d70Mb8bg8XkiyzI1 einqMYtOKslsA3bRDmRnSQz1pQvf2ogispBEC21/3KBZZC9Zbiw9lm4wa9NIpqQUujN3 DwFIQlKlfE2L11FbwuGn46JnfX+APEzIWXEbuZd5LF5zAOxRhCJMVvZIop42lyDRaYuo VtP0XbqFk0ETLAge8kjVYLD/uPxYCkBLpoFgldwCcBWJvqGparDR2Z5ScnaGQt5AHDrI U22A== X-Forwarded-Encrypted: i=1; AJvYcCXQKOrOoG0NTlNcCQF0Cnmqx/2msqtqUMtRg07Yn22wR7KDFQuGGTG6w9aXIoUH0Wn7e1DhAwI+Gzv1unQ=@vger.kernel.org X-Gm-Message-State: AOJu0YxQdgoKsBdvDx2dP77Xb0rbxtanG7+XqW6CSF//06eCtZCiTAmR 4ADB52JKfhk19cjyz+pgkEfJum3mTUJcLR5hl3skOGZ1hvfmZffW X-Gm-Gg: ASbGncuJmTtPHekjpVmtX813QLrC73qzyLbYWg3RDSsFO9CLxxZouUN6u9PPGsMAfh9 zRxVkr2HI8ItUIXs42xGUmsrMK+rQC03YenhIxLni15YOxWMOhqj6j5E+WiUkY3vYDJCe/bk4zu WBWo0uk8tTjEyOS0Lvne+3s3TbXQ1aJrzxOWfAlql+Fqm4Z5jm5zWDXc9IGV/jnf10DTDi6NIFa trZ0DC3mWx/V+qb5sNM8pLQEbsSgJ/sTT2LwxDl1GuqLduEEhapcZ2N/8LkOM5hbIk3/kSqjWsX SviDoBf9idl6f2sBWbAcIQ6OJk51Lew3tLFL4+lmhO50PkgYUoju/aoGZ0VFY75BSHPNLzG5RCJ zRB4k8CY9NOk1qLDSLyMoNthpcxDTBw== X-Google-Smtp-Source: AGHT+IHDnCL35LzEftESps1dx2w0AZDEuvmI8snCKPzT1aQCqtwrXOPbRoX+rcH6Lt6A5Kcmxnl0VA== X-Received: by 2002:a17:906:ad7:b0:acb:b8bd:ddf9 with SMTP id a640c23a62f3a-acbb8bde169mr48690366b.0.1745273224054; Mon, 21 Apr 2025 15:07:04 -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 a640c23a62f3a-acbb8d49fdasm80311666b.67.2025.04.21.15.07.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 21 Apr 2025 15:07: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 v7 09/11] iio: accel: adxl345: add inactivity feature Date: Mon, 21 Apr 2025 22:06:39 +0000 Message-Id: <20250421220641.105567-10-l.rubusch@gmail.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250421220641.105567-1-l.rubusch@gmail.com> References: <20250421220641.105567-1-l.rubusch@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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 | 172 ++++++++++++++++++++++++++++++- 1 file changed, 167 insertions(+), 5 deletions(-) diff --git a/drivers/iio/accel/adxl345_core.c b/drivers/iio/accel/adxl345_c= ore.c index 680981609d83..b25efcad069b 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 | ADXL34= 5_POWER_CTL_LINK) =20 #define ADXL345_TAP_Z_EN BIT(0) #define ADXL345_TAP_Y_EN BIT(1) #define ADXL345_TAP_X_EN BIT(2) =20 +#define ADXL345_INACT_Z_EN BIT(0) +#define ADXL345_INACT_Y_EN BIT(1) +#define ADXL345_INACT_X_EN BIT(2) + #define ADXL345_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[] =3D { /* activity/inactivity */ enum adxl345_activity_type { ADXL345_ACTIVITY, + ADXL345_INACTIVITY, }; =20 static const unsigned int adxl345_act_int_reg[] =3D { [ADXL345_ACTIVITY] =3D ADXL345_INT_ACTIVITY, + [ADXL345_INACTIVITY] =3D ADXL345_INT_INACTIVITY, }; =20 static const unsigned int adxl345_act_thresh_reg[] =3D { [ADXL345_ACTIVITY] =3D ADXL345_REG_THRESH_ACT, + [ADXL345_INACTIVITY] =3D ADXL345_REG_THRESH_INACT, }; =20 enum adxl345_odr { @@ -232,6 +241,16 @@ static const struct iio_event_spec adxl345_freefall_ev= ent_spec =3D { BIT(IIO_EV_INFO_PERIOD), }; =20 +/* inactivity */ +static const struct iio_event_spec adxl345_inactivity_event_spec =3D { + .type =3D IIO_EV_TYPE_THRESH, + .dir =3D IIO_EV_DIR_FALLING, + .mask_separate =3D BIT(IIO_EV_INFO_ENABLE), + .mask_shared_by_type =3D BIT(IIO_EV_INFO_VALUE) | + BIT(IIO_EV_INFO_PERIOD), + +}; + static const struct iio_chan_spec adxl345_channels[] =3D { ADXL345_CHANNEL(0, chan_x, X), ADXL345_CHANNEL(1, chan_y, Y), @@ -244,6 +263,14 @@ static const struct iio_chan_spec adxl345_channels[] = =3D { .event_spec =3D &adxl345_freefall_event_spec, .num_event_specs =3D 1, }, + { + .type =3D IIO_ACCEL, + .modified =3D 1, + .channel2 =3D IIO_MOD_X_AND_Y_AND_Z, + .scan_index =3D -1, /* Fake channel */ + .event_spec =3D &adxl345_inactivity_event_spec, + .num_event_specs =3D 1, + }, }; =20 static const unsigned long adxl345_scan_masks[] =3D { @@ -287,7 +314,8 @@ static int adxl345_set_measure_en(struct adxl345_state = *st, bool en) { unsigned int val =3D en ? ADXL345_POWER_CTL_MEASURE : ADXL345_POWER_CTL_S= TANDBY; =20 - return regmap_write(st->regmap, ADXL345_REG_POWER_CTL, val); + return regmap_update_bits(st->regmap, ADXL345_REG_POWER_CTL, + ADXL345_POWER_CTL_MEASURE, val); } =20 /* act/inact */ @@ -319,6 +347,21 @@ static int adxl345_is_act_inact_en(struct adxl345_stat= e *st, *en =3D false; return -EINVAL; } + } else { + switch (axis) { + case IIO_MOD_X: + *en =3D FIELD_GET(ADXL345_INACT_X_EN, axis_ctrl); + break; + case IIO_MOD_Y: + *en =3D FIELD_GET(ADXL345_INACT_Y_EN, axis_ctrl); + break; + case IIO_MOD_Z: + *en =3D FIELD_GET(ADXL345_INACT_Z_EN, axis_ctrl); + break; + default: + *en =3D false; + return -EINVAL; + } } =20 if (*en) { @@ -338,6 +381,7 @@ static int adxl345_set_act_inact_en(struct adxl345_stat= e *st, bool cmd_en) { bool en; + unsigned int inact_time_s; unsigned int threshold; u32 axis_ctrl =3D 0; int ret; @@ -356,6 +400,9 @@ static int adxl345_set_act_inact_en(struct adxl345_stat= e *st, default: return -EINVAL; } + } else { + axis_ctrl =3D ADXL345_INACT_X_EN | ADXL345_INACT_Y_EN | + ADXL345_INACT_Z_EN; } =20 if (cmd_en) @@ -376,11 +423,69 @@ static int adxl345_set_act_inact_en(struct adxl345_st= ate *st, if (type =3D=3D ADXL345_ACTIVITY) { en =3D FIELD_GET(ADXL345_REG_ACT_AXIS_MSK, axis_ctrl) && threshold; + } else { + ret =3D regmap_read(st->regmap, ADXL345_REG_TIME_INACT, &inact_time_s); + if (ret) + return ret; + + en =3D FIELD_GET(ADXL345_REG_INACT_AXIS_MSK, axis_ctrl) && + threshold && inact_time_s; } =20 - return regmap_update_bits(st->regmap, ADXL345_REG_INT_ENABLE, - adxl345_act_int_reg[type], - en ? adxl345_act_int_reg[type] : 0); + ret =3D 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 O= DR. + * @st: The sensor state instance. + * @val_s: A desired time value, between 0 and 255. + * + * Inactivity time can be configured between 1 and 255 sec. If a val_s of 0 + * is configured by a user, then a default inactivity time will be compute= d. + * + * In such case, it should take power consumption into consideration. Thus= it + * shall be shorter for higher frequencies and longer for lower frequencie= s. + * Hence, frequencies above 255 Hz shall default to 10 s and frequencies b= elow + * 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 =3D 255; + unsigned int min_boundary =3D 10; + unsigned int val =3D min(val_s, max_boundary); + enum adxl345_odr odr; + unsigned int regval; + int ret; + + if (val =3D=3D 0) { + ret =3D regmap_read(st->regmap, ADXL345_REG_BW_RATE, ®val); + if (ret) + return ret; + odr =3D FIELD_GET(ADXL345_BW_RATE_MSK, regval); + + val =3D (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); } =20 /* tap */ @@ -846,6 +951,13 @@ static int adxl345_read_event_config(struct iio_dev *i= ndio_dev, if (ret) return ret; return int_en; + case IIO_EV_DIR_FALLING: + ret =3D adxl345_is_act_inact_en(st, chan->channel2, + ADXL345_INACTIVITY, + &int_en); + if (ret) + return ret; + return int_en; default: return -EINVAL; } @@ -890,6 +1002,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; } @@ -917,7 +1032,8 @@ static int adxl345_read_event_value(struct iio_dev *in= dio_dev, int *val, int *val2) { struct adxl345_state *st =3D 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; @@ -936,9 +1052,24 @@ static int adxl345_read_event_value(struct iio_dev *i= ndio_dev, =20 *val =3D act_threshold; return IIO_VAL_INT; + case IIO_EV_DIR_FALLING: + ret =3D regmap_read(st->regmap, + adxl345_act_thresh_reg[ADXL345_INACTIVITY], + &inact_threshold); + if (ret) + return ret; + + *val =3D inact_threshold; + return IIO_VAL_INT; default: return -EINVAL; } + case IIO_EV_INFO_PERIOD: + ret =3D regmap_read(st->regmap, ADXL345_REG_TIME_INACT, &inact_time_s); + if (ret) + return ret; + *val =3D inact_time_s; + return IIO_VAL_INT; default: return -EINVAL; } @@ -1019,10 +1150,22 @@ static int adxl345_write_event_value(struct iio_dev= *indio_dev, if (ret) return ret; break; + case IIO_EV_DIR_FALLING: + ret =3D 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 =3D adxl345_set_inact_time_s(st, val); + if (ret) + return ret; + break; default: return -EINVAL; } @@ -1323,6 +1466,17 @@ static int adxl345_push_event(struct iio_dev *indio_= dev, int int_stat, return ret; } =20 + if (FIELD_GET(ADXL345_INT_INACTIVITY, int_stat)) { + ret =3D iio_push_event(indio_dev, + IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, + IIO_MOD_X_AND_Y_AND_Z, + IIO_EV_TYPE_THRESH, + IIO_EV_DIR_FALLING), + ts); + if (ret) + return ret; + } + if (FIELD_GET(ADXL345_INT_FREE_FALL, int_stat)) { ret =3D iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, @@ -1569,10 +1723,18 @@ int adxl345_core_probe(struct device *dev, struct r= egmap *regmap, if (ret) return ret; =20 + ret =3D regmap_write(st->regmap, ADXL345_REG_TIME_INACT, 3); + if (ret) + return ret; + ret =3D regmap_write(st->regmap, ADXL345_REG_THRESH_ACT, 6); if (ret) return ret; =20 + ret =3D regmap_write(st->regmap, ADXL345_REG_THRESH_INACT, 4); + if (ret) + return ret; + ret =3D regmap_write(st->regmap, ADXL345_REG_THRESH_TAP, tap_threshold); if (ret) return ret; --=20 2.39.5 From nobody Tue Dec 16 21:01:36 2025 Received: from mail-ej1-f48.google.com (mail-ej1-f48.google.com [209.85.218.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 1CB96223706; Mon, 21 Apr 2025 22:07:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.48 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1745273229; cv=none; b=OGIUYC83U+cMrSqAqMsuekJTl4I2RxcnkBUWzVjrPVCM2u+uZkwILKf7I41FbY5QJDRetPl0rjIDcKaqNTXmKShfwI13R7WLLF+jdW5cwEcNsU/wncWLHIgbhyn/va5CGWlFxQZpo+t1cuXkujzEvXyyW2VLyi1awAPNjwM7pxg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1745273229; c=relaxed/simple; bh=VjvsnNSbg1Cc4C8TpUgNdabih6kCHuQ/c1PuLjBoSdw=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=Tna0+vdphyeo61ZJLcM0fS6QjDG7fX10lOmK8GJ56/uv4G44Dt707fduU3DZJLBlY/ULMJLXYzErXBPK9oKS3onYAcC4iPGPxkX/c35Kj5wVLoNl5Z5dg6WrGwD0LinfS6nYS4/Vdte0vF5h9Gv3CWo5qzyPLoOP/6VTQgRp+ec= 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=F3q4Koge; arc=none smtp.client-ip=209.85.218.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="F3q4Koge" Received: by mail-ej1-f48.google.com with SMTP id a640c23a62f3a-acba3f5868eso17916366b.1; Mon, 21 Apr 2025 15:07:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1745273225; x=1745878025; 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=MZr0T5SXjPShcJbHgJIn0GUT2qyjdnoec7oYBKEuV84=; b=F3q4KogeIa6jzODekHX0r859Wy3px8R1a1louqXadEu9DXxI970qs21sGJPUhxGz2j n2HRPu5QthMSua7EgNhIGHZGil/hYPCsJIaPBrlzfnip/q5SKQoRtFcdDaKVtd0kRqWM MqNXjSDEAl1/7TJycvWU87nwcc5uOrxv24RX8QVsEagdVPrrB9uwHI8HKuMxnxSGBeJA Jp45wLwD98UF63p/BGEwDnJmWUDSR9UrdvfZKGM+ddfYszRs6ie4hHBio0yJ2kBjRvOU hT95OO3SPwwRNRJ5QFQFsNM31UXJPMaT2mJUv3ueDHeDZMntgD+qrQyMQvEkrf87dIOn waKA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1745273225; x=1745878025; 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=MZr0T5SXjPShcJbHgJIn0GUT2qyjdnoec7oYBKEuV84=; b=Mh0W41VddzPGo2BBoOtbDc8M8VE1BtFgiWK4Gc6tmC0DT/Sy3UfYmowkIJRIbuN2Th fYGsEK84cvhPwsJbXSYDzAK+tVpfnVsQEHbMI7ZxeUGj+crIxAG/ZvL+HlLaCfQj0Kpa 3ktws3Fb1RGJRPsyMX5i0/kXAXmO0qFFt136ui5h3Irex9x9xw1T1Te8FTgFWLfdSRHQ ftp4V1qoPnvUwuJiKTeXVbk1eU/H9mpLW5StjER/BwlRlSM+GtwLD4xmFOleHj/G6b7g JdJFtegzgwsZjvUazLAK0AmjR6mlEETRUFtwwtkqSAETcWBtv96btGOAxs1Yasu1InIt ZY8g== X-Forwarded-Encrypted: i=1; AJvYcCUuFSHN0bmH8CBhtXdN0Gz9A8v1tpYcrWvc1c/M4bDJjA8QzJFQuQoQcRrA3fdfqhoNmxUqEu3GR1plAhA=@vger.kernel.org X-Gm-Message-State: AOJu0Yzpw6KXhalITTOWbZbtN68OqEBWwVwGiirOTLOFjnhxXX1aDHqV MXdhjS46DK3B75urmVunXW6Y+az934kYWSoPL4SZGAUNvb+ByT8O X-Gm-Gg: ASbGnctIztXLYUOeKO1hC+S5v6uYEMualWU2pCYZaYcfuldN6/6NKyI+UUZzbkITSLS 0ORERxUL4sJL2im0TQURyafxe0XQygMhc0b+s50Kk9t6VfSlDXa64xSJmZqt1cmb8RNxChGdSGc b5xsjKHjyuGbrrfho7R5iWewGpudnBiYSKI0tOsbC95nM+d4LmjYol5pCkwLniwmDL96oMfEvLN f/KdLsNJlcW/uff0jlLVh6W7ErPQQXWnaPj/k1KyrPNBZHeT/mM+yy1+PxDGa0gQyj0Rz2aUeXN I7u9azKtlTSCG6BPueeOmN8zQE8HkLHzdTyiIiEommh00gKY5qKuusPBQZ5n7mtjaUyrJ51JiKf UDYuV3Lun+r5ByZebSrQ= X-Google-Smtp-Source: AGHT+IH/5JAfyrS1Fx6teO+9qCIIag18/kxUkcz4BZ3XKGqyCGd9JggM0MqCm04CQfhMKvaDYWaBwA== X-Received: by 2002:a17:906:5ad5:b0:acb:7de1:28b9 with SMTP id a640c23a62f3a-acb7de12b80mr319562166b.5.1745273225108; Mon, 21 Apr 2025 15:07: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 a640c23a62f3a-acbb8d49fdasm80311666b.67.2025.04.21.15.07.04 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 21 Apr 2025 15:07: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 v7 10/11] iio: accel: adxl345: add coupling detection for activity/inactivity Date: Mon, 21 Apr 2025 22:06:40 +0000 Message-Id: <20250421220641.105567-11-l.rubusch@gmail.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250421220641.105567-1-l.rubusch@gmail.com> References: <20250421220641.105567-1-l.rubusch@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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, 159 insertions(+), 3 deletions(-) diff --git a/drivers/iio/accel/adxl345_core.c b/drivers/iio/accel/adxl345_c= ore.c index b25efcad069b..c07ad5774c8a 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 | ADXL34= 5_POWER_CTL_LINK) =20 #define ADXL345_TAP_Z_EN BIT(0) @@ -91,6 +93,11 @@ static const unsigned int adxl345_act_thresh_reg[] =3D { [ADXL345_INACTIVITY] =3D ADXL345_REG_THRESH_INACT, }; =20 +static const unsigned int adxl345_act_acdc_msk[] =3D { + [ADXL345_ACTIVITY] =3D ADXL345_REG_ACT_ACDC_MSK, + [ADXL345_INACTIVITY] =3D ADXL345_REG_INACT_ACDC_MSK, +}; + enum adxl345_odr { ADXL345_ODR_0P10HZ =3D 0, ADXL345_ODR_0P20HZ, @@ -204,6 +211,18 @@ static struct iio_event_spec adxl345_events[] =3D { BIT(IIO_EV_INFO_RESET_TIMEOUT) | BIT(IIO_EV_INFO_TAP2_MIN_DELAY), }, + { + /* activity, activity - ac bit */ + .type =3D IIO_EV_TYPE_MAG_REFERENCED, + .dir =3D IIO_EV_DIR_RISING, + .mask_shared_by_type =3D BIT(IIO_EV_INFO_ENABLE), + }, + { + /* activity, inactivity - ac bit */ + .type =3D IIO_EV_TYPE_MAG_REFERENCED, + .dir =3D IIO_EV_DIR_FALLING, + .mask_shared_by_type =3D BIT(IIO_EV_INFO_ENABLE), + }, }; =20 #define ADXL345_CHANNEL(index, reg, axis) { \ @@ -320,6 +339,69 @@ static int adxl345_set_measure_en(struct adxl345_state= *st, bool en) =20 /* act/inact */ =20 +static int adxl345_is_act_inact_ac(struct adxl345_state *st, + enum adxl345_activity_type type, bool *ac) +{ + unsigned int regval; + int ret; + + ret =3D regmap_read(st->regmap, ADXL345_REG_ACT_INACT_CTRL, ®val); + if (ret) + return ret; + + if (type =3D=3D ADXL345_ACTIVITY) + *ac =3D FIELD_GET(ADXL345_REG_ACT_ACDC_MSK, regval); + else + *ac =3D FIELD_GET(ADXL345_REG_INACT_ACDC_MSK, regval); + + 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 =3D 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) @@ -774,9 +856,16 @@ static int adxl345_find_odr(struct adxl345_state *st, = int val, =20 static int adxl345_set_odr(struct adxl345_state *st, enum adxl345_odr odr) { - return regmap_update_bits(st->regmap, ADXL345_REG_BW_RATE, + int ret; + + ret =3D regmap_update_bits(st->regmap, ADXL345_REG_BW_RATE, ADXL345_BW_RATE_MSK, FIELD_PREP(ADXL345_BW_RATE_MSK, odr)); + if (ret) + return ret; + + /* update inactivity time by ODR */ + return adxl345_set_inact_time_s(st, 0); } =20 static int adxl345_find_range(struct adxl345_state *st, int val, int val2, @@ -797,9 +886,51 @@ static int adxl345_find_range(struct adxl345_state *st= , int val, int val2, =20 static int adxl345_set_range(struct adxl345_state *st, enum adxl345_range = range) { - return regmap_update_bits(st->regmap, ADXL345_REG_DATA_FORMAT, + unsigned int act_threshold, inact_threshold; + unsigned int range_old; + unsigned int regval; + int ret; + + ret =3D regmap_read(st->regmap, ADXL345_REG_DATA_FORMAT, ®val); + if (ret) + return ret; + range_old =3D FIELD_GET(ADXL345_DATA_FORMAT_RANGE, regval); + + ret =3D regmap_read(st->regmap, + adxl345_act_thresh_reg[ADXL345_ACTIVITY], + &act_threshold); + if (ret) + return ret; + + ret =3D regmap_read(st->regmap, + adxl345_act_thresh_reg[ADXL345_INACTIVITY], + &inact_threshold); + if (ret) + return ret; + + ret =3D regmap_update_bits(st->regmap, ADXL345_REG_DATA_FORMAT, ADXL345_DATA_FORMAT_RANGE, FIELD_PREP(ADXL345_DATA_FORMAT_RANGE, range)); + if (ret) + return ret; + + act_threshold =3D act_threshold + * adxl345_range_factor_tbl[range_old] + / adxl345_range_factor_tbl[range]; + act_threshold =3D min(255, max(1, inact_threshold)); + + inact_threshold =3D inact_threshold + * adxl345_range_factor_tbl[range_old] + / adxl345_range_factor_tbl[range]; + inact_threshold =3D min(255, max(1, inact_threshold)); + + ret =3D regmap_write(st->regmap, adxl345_act_thresh_reg[ADXL345_ACTIVITY], + act_threshold); + if (ret) + return ret; + + return regmap_write(st->regmap, adxl345_act_thresh_reg[ADXL345_INACTIVITY= ], + inact_threshold); } =20 static int adxl345_read_avail(struct iio_dev *indio_dev, @@ -938,7 +1069,7 @@ static int adxl345_read_event_config(struct iio_dev *i= ndio_dev, enum iio_event_direction dir) { struct adxl345_state *st =3D iio_priv(indio_dev); - bool int_en; + bool int_en, act_ac, inact_ac; int ret; =20 switch (type) { @@ -983,6 +1114,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 =3D adxl345_is_act_inact_ac(st, ADXL345_ACTIVITY, &act_ac); + if (ret) + return ret; + return act_ac; + case IIO_EV_DIR_FALLING: + ret =3D adxl345_is_act_inact_ac(st, ADXL345_INACTIVITY, &inact_ac); + if (ret) + return ret; + return inact_ac; + default: + return -EINVAL; + } default: return -EINVAL; } @@ -1019,6 +1165,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; } --=20 2.39.5 From nobody Tue Dec 16 21:01:36 2025 Received: from mail-ed1-f47.google.com (mail-ed1-f47.google.com [209.85.208.47]) (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 1520221CA1C; Mon, 21 Apr 2025 22:07:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.47 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1745273230; cv=none; b=PrjdTljj7XHzNhnttd3Bn6vphRvPv9bFefIB9KJ40N1Il428tNo2et8R8LDB6M0J/2gsWzzrUgC9sf1AISYia/ibg1PbE7SSqchdLN8pmSIdjpdWxo9CrKLwrf7ME+taOG/Dx6OQ0T+Swz0hp2K6MJX6jeL+OV2WhkbEgXbW8Qc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1745273230; c=relaxed/simple; bh=+NifVuQO9x5JbghGrqSQsE6DlY3y/pAS32e259uP1js=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version:Content-Type; b=Vhlfrkxg2efOI01uvmg9ONyNMDASi2zD5KCf1czepq7O7dwpOckjJ1rFWHcRApqMGzbWyiF28ldc8rNDt1/pfTgL/n+m3hvXYt/k/5uaZgSaTMuGUxrqlkw0k3yuuckEL6irrmS7JJpyLXxw3wn+gDKs8O+VLrcILv/F3Qc8wcs= 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=T5OcDpRM; arc=none smtp.client-ip=209.85.208.47 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="T5OcDpRM" Received: by mail-ed1-f47.google.com with SMTP id 4fb4d7f45d1cf-5f121612dabso622434a12.1; Mon, 21 Apr 2025 15:07:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1745273226; x=1745878026; 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=x2EDZgRwJRT7jx/AB7jRUIQcQXxW+YuIn1RIegx7Ti4=; b=T5OcDpRM5rGRICXoGP6fV8GWXnLo9sAhPGvBxkBnMbqunJA/WHzmOKXj+mZHiCcDQ7 vyQdAMM/G1H91HxcYGFXFHnTGnF8vd6EreK0f//e3pLeKAXV6WmZzC+4vwZ0+/aL1Ycz PjPE5uAe8xDwD4TF+/Nf0IKmKIwmf2hpWmklGEHkgQmYAECtEcGD5spPl/oyCDo/+4W7 LqT8nfU78HjP4S1MsK37q+1lEdSZF9Z+WKjocUDoBgLwDZ5Pd9zROs8sWfdpahJaMW0F J95Va01qmOYwnp3KRHriGA6DetGqE+MeVrHxA/NwicidwAyCGK0PdfKFvf0+gvW4gmmb mE9w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1745273226; x=1745878026; 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=x2EDZgRwJRT7jx/AB7jRUIQcQXxW+YuIn1RIegx7Ti4=; b=BnFu/3WEQ98iKlzlt8Q6Ar62lHrUY7KtNsVaR7bEXc1Y1ZYGsniciMoE1vWmtCFPu1 diHF5edjZ0YwxfggvXIIXJLr4RjKtGv2uGDKtiN/l8nlzv32pP/wktSGakGkUZUCJwYZ 8TtefzkdzZP+rcRogm3U7lTK4lLsZXz8IKqGWYJKCiHJs6KOs5mQuPOBVdcjMIcayFqZ hYwk3Sden/DXyS+zms6ZcoPTSfo9wcwiibml2Zz66B4mM2djfDMyJcpJsGz/ccBjj0Gd FwJbxyY3EaFEgA5BPS6ap3k2A8K9hxSON3yocw1hPyW/LEJW02bjrEHmN3PAGbz3MbB4 lUjw== X-Forwarded-Encrypted: i=1; AJvYcCWFG2zkkbH/tvqLj6dKOxmhWoEwRbeJi+3rsd0BM3PwuM4dcPJTDRVU1SvI3uU/alaNtr6wlEJKD9yV288=@vger.kernel.org X-Gm-Message-State: AOJu0Yy24SmdOQkf14yxf1ZkaXfRs6xZHiqSWOmiB1Vn1frDEdZmVoiA Evskz4wxuF0ig6SEnzes6ZJh6TXM5tUzUToHLf9M86Qm1rbU4hKXipcJhA== X-Gm-Gg: ASbGncuUo7F5l8KRqQYvdxiwJGnU48sm5aG8MZ2Hh7wL7L2+Yf8844TgVIjei3Pk/cq zWQoQA9RIVFQtD9y5RE1jd83XUkN+kmfIyQuk36BP7PCqAj4u4jwVSM3Ouv8CT2aovrx0Jnosxh DeNJ+WudGfbfBdlmxh2yV3caWHF4bt5BHLJJ7l++P6lHMd90FUBz0G9ET3sz7dOuxLk/14uiaLp G6cpRJwnEPuM5v6vvOsXV8bGMiNNbkffw68e6RgCnP+gZN85JgYkwAmGouF4xWscE9BfwxXjXSu rcsvCbk3ry2YpEH/yIH4cjMPhVNyOj8uPcJlt1ECwGLgm2RwD+yMjs7Px1KMQvC47LA9/xl24le SUHhVxkUBPKZHA345Tyc= X-Google-Smtp-Source: AGHT+IGWa4ho70tDGBwCv8Mpqfjgo4GRDT2Kcj9nBkEjpnJY35Gi5idPiPYFwV0DAkNJmri96HxXtQ== X-Received: by 2002:a05:6402:430f:b0:5f5:5064:47f3 with SMTP id 4fb4d7f45d1cf-5f628532f89mr3974527a12.3.1745273226164; Mon, 21 Apr 2025 15:07: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 a640c23a62f3a-acbb8d49fdasm80311666b.67.2025.04.21.15.07.05 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 21 Apr 2025 15:07: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 v7 11/11] docs: iio: add documentation for adxl345 driver Date: Mon, 21 Apr 2025 22:06:41 +0000 Message-Id: <20250421220641.105567-12-l.rubusch@gmail.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250421220641.105567-1-l.rubusch@gmail.com> References: <20250421220641.105567-1-l.rubusch@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable The documentation describes the ADXL345 driver, IIO interface, interface usage and configuration. Signed-off-by: Lothar Rubusch --- Documentation/iio/adxl345.rst | 423 ++++++++++++++++++++++++++++++++++ 1 file changed, 423 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..e12fe280a94f --- /dev/null +++ b/Documentation/iio/adxl345.rst @@ -0,0 +1,423 @@ +.. SPDX-License-Identifier: GPL-2.0 + +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D +ADXL345 driver +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +This driver supports Analog Device's ADXL345/375 on SPI/I2C bus. + +1. Supported Devices +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +* `ADXL345 `_ +* `ADXL375 `_ + +The ADXL345 is a generic purpose low power, 3-axis accelerometer with sele= ctable +measurement ranges. The ADXL345 supports the =C2=B12 g, =C2=B14 g, =C2=B18= g, and =C2=B116 g ranges. + +2. Device Attributes +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +Each IIO device, has a device folder under ``/sys/bus/iio/devices/iio:devi= ceX``, +where X is the IIO index of the device. Under these folders reside a set of +device files, depending on the characteristics and features of the hardware +device in questions. These files are consistently generalized and document= ed in +the IIO ABI documentation. + +The following table shows the ADXL345 related device files, found in the +specific device folder path ``/sys/bus/iio/devices/iio:deviceX``. + ++-------------------------------------------+-----------------------------= -----------------------------+ +| 3-Axis Accelerometer related device files | Description = | ++-------------------------------------------+-----------------------------= -----------------------------+ +| in_accel_sampling_frequency | Currently selected sample ra= te. | ++-------------------------------------------+-----------------------------= -----------------------------+ +| in_accel_sampling_frequency_available | Available sampling frequency= configurations. | ++-------------------------------------------+-----------------------------= -----------------------------+ +| in_accel_scale | Scale/range for the accelero= meter channels. | ++-------------------------------------------+-----------------------------= -----------------------------+ +| in_accel_scale_available | Available scale ranges for t= he accelerometer channel. | ++-------------------------------------------+-----------------------------= -----------------------------+ +| in_accel_x_calibbias | Calibration offset for the X= -axis accelerometer channel. | ++-------------------------------------------+-----------------------------= -----------------------------+ +| in_accel_x_raw | Raw X-axis accelerometer cha= nnel value. | ++-------------------------------------------+-----------------------------= -----------------------------+ +| in_accel_y_calibbias | y-axis acceleration offset c= orrection | ++-------------------------------------------+-----------------------------= -----------------------------+ +| in_accel_y_raw | Raw Y-axis accelerometer cha= nnel value. | ++-------------------------------------------+-----------------------------= -----------------------------+ +| in_accel_z_calibbias | Calibration offset for the Z= -axis accelerometer channel. | ++-------------------------------------------+-----------------------------= -----------------------------+ +| in_accel_z_raw | Raw Z-axis accelerometer cha= nnel value. | ++-------------------------------------------+-----------------------------= -----------------------------+ + +Channel Processed Values +------------------------- + +A channel value can be read from its _raw attribute. The value returned is= the +raw value as reported by the devices. To get the processed value of the ch= annel, +apply the following formula: + +.. code-block:: bash + + processed value =3D (_raw + _offset) * _scale + +Where _offset and _scale are device attributes. If no _offset attribute is +present, simply assume its value is 0. + ++-------------------------------------+---------------------------+ +| Channel type | Measurement unit | ++-------------------------------------+---------------------------+ +| Acceleration on X, Y, and Z axis | Meters per second squared | ++-------------------------------------+---------------------------+ + +Sensor Events +------------- + +Particular IIO events will be triggered by the corresponding interrupts. T= he +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 detectio= n on all axis | ++---------------------------------------------+---------------------------= --------------+ +| in_accel_gesture_doubletap_reset_timeout | Double tap window in [us] = | ++---------------------------------------------+---------------------------= --------------+ +| in_accel_gesture_doubletap_tap2_min_delay | Double tap latent in [us] = | ++---------------------------------------------+---------------------------= --------------+ +| in_accel_gesture_singletap_timeout | Single tap duration in [us= ] | ++---------------------------------------------+---------------------------= --------------+ +| in_accel_gesture_singletap_value | Single tap threshold value= in 62.5/LSB | ++---------------------------------------------+---------------------------= --------------+ +| in_accel_x&y&z_mag_falling_en | Enable free fall detection= on all axis | ++---------------------------------------------+---------------------------= --------------+ +| 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 inacti= vity, 0 for DC| ++---------------------------------------------+---------------------------= --------------+ +| in_accel_mag_referenced_rising_en | Set 1 to AC-coupled activi= ty, 0 for DC | ++---------------------------------------------+---------------------------= --------------+ +| in_accel_x&y&z_thresh_falling_en | Enable inactivity detectio= n on all 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 i= n 62.5/LSB | ++---------------------------------------------+---------------------------= --------------+ +| in_accel_x_gesture_singletap_en | Enable single tap detectio= n on X axis | ++---------------------------------------------+---------------------------= --------------+ +| in_accel_y_gesture_singletap_en | Enable single tap detectio= n on Y axis | ++---------------------------------------------+---------------------------= --------------+ +| in_accel_z_gesture_singletap_en | Enable single tap detectio= n on Z axis | ++---------------------------------------------+---------------------------= --------------+ + +Find a detailed description of a particular functionality in the sensor +datasheet. + +Setting the **ODR** explicitly will result in estimated adjusted default v= alues +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 settin= g. + +The **g range** configuration also tries to estimate activity and inactivi= ty +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 ne= ver +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 enabled, the driver automa= tically +will implement its hysteresis solution by setting link bit and autosleep b= it. +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. Inactivity time can be configured between 1s and 255s. Wh= en 0 +is configured as inactivity time, the driver will define a reasonable value +depending on a heuristic approach to optimize power consumption. + +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 ta= ken +as a reference value. New samples are then compared to this reference valu= e. +Note, ac-coupling and dc-coupling are individually set for activity and/or +inactivity detection. Activity detection can be enabled on particular axis. +Inactivity detection on the other side, is enabled or disabled on all axis. + +**Single tap** detection can be configured according to the datasheet by s= pecifying +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 si= ngle +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]. Late= ncy +starts counting when the single tap goes below threshold and is a waiting +period, any spikes here are ignored for double tap detection. After latenc= y, +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. Therefo= re the +signal must match several criteria, and detection can also considered inva= lid +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 doub= le tap +detection immediately, i.e. during latency must not occur spikes for doubl= e 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 config= ured +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_calibb= ias + root:/sys/bus/iio/devices/iio:device0> cat in_accel_x_calibbias + 50 + +Given the 13-bit full resolution, the available ranges are calculated by t= he +following forumla: + +.. code-block:: bash + + (g * 2 * 9.80665) / (2^(resolution) - 1) * 100; for g :=3D 2|4|8|16 + +Scale range configuration: + +.. code-block:: bash + + root:/sys/bus/iio/devices/iio:device0> cat ./in_accel_scale + 0.478899 + root:/sys/bus/iio/devices/iio:device0> cat ./in_accel_scale_availa= ble + 0.478899 0.957798 1.915595 3.831190 + + root:/sys/bus/iio/devices/iio:device0> echo 1.915595 > ./in_accel_= scale + root:/sys/bus/iio/devices/iio:device0> cat ./in_accel_scale + 1.915595 + +Set output data rate (ODR): + +.. code-block:: bash + + root:/sys/bus/iio/devices/iio:device0> cat ./in_accel_sampling_fre= quency + 200.000000 + + root:/sys/bus/iio/devices/iio:device0> cat ./in_accel_sampling_fre= quency_available + 0.097000 0.195000 0.390000 0.781000 1.562000 3.125000 6.250000 12.= 500000 25.000000 50.000000 100.000000 200.000000 400.000000 800.000000 1600= .000000 3200.000000 + + root:/sys/bus/iio/devices/iio:device0> echo 1.562000 > ./in_accel_= sampling_frequency + root:/sys/bus/iio/devices/iio:device0> cat ./in_accel_sampling_fre= quency + 1.562000 + +Configure one or several events: + +.. code-block:: bash + + root:> cd /sys/bus/iio/devices/iio:device0 + + root:/sys/bus/iio/devices/iio:device0> echo 1 > ./buffer0/in_accel= _x_en + root:/sys/bus/iio/devices/iio:device0> echo 1 > ./buffer0/in_accel= _y_en + root:/sys/bus/iio/devices/iio:device0> echo 1 > ./buffer0/in_accel= _z_en + + root:/sys/bus/iio/devices/iio:device0> echo 1 > ./scan_elements/in= _accel_x_en + root:/sys/bus/iio/devices/iio:device0> echo 1 > ./scan_elements/in= _accel_y_en + root:/sys/bus/iio/devices/iio:device0> echo 1 > ./scan_elements/in= _accel_z_en + + root:/sys/bus/iio/devices/iio:device0> echo 14 > ./in_accel_x_ca= libbias + root:/sys/bus/iio/devices/iio:device0> echo 2 > ./in_accel_y_ca= libbias + root:/sys/bus/iio/devices/iio:device0> echo -250 > ./in_accel_z_ca= libbias + + root:/sys/bus/iio/devices/iio:device0> echo 24 > ./buffer0/length + + ## 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/i= n_accel_gesture_singletap_timeout + + ## doubletap, window [us] + root:/sys/bus/iio/devices/iio:device0> echo 0.025 > ./events/in_ac= cel_gesture_doubletap_reset_timeout + + ## doubletap, latent [us] + root:/sys/bus/iio/devices/iio:device0> echo 0.025 > ./events/in_ac= cel_gesture_doubletap_tap2_min_delay + + ## 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_acc= el_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_= x\&y\&z_thresh_falling_en + + ## freefall, enable + root:/sys/bus/iio/devices/iio:device0> echo 1 > ./events/in_accel_= x\&y\&z_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, evty= pe: thresh, direction: rising + Event: time: 1739063415963770218, type: accel(z), channel: 0, evty= pe: thresh, direction: rising + Event: time: 1739063416002563061, type: accel(z), channel: 0, evty= pe: gesture, direction: singletap + Event: time: 1739063426271128739, type: accel(x&y&z), channel: 0, = evtype: 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, evty= pe: thresh, direction: rising + Event: time: 1739063446726161586, type: accel(z), channel: 0, evty= pe: thresh, direction: rising + Event: time: 1739063446727892670, type: accel(z), channel: 0, evty= pe: thresh, direction: rising + Event: time: 1739063446743019768, type: accel(z), channel: 0, evty= pe: thresh, direction: rising + Event: time: 1739063446744650696, type: accel(z), channel: 0, evty= pe: thresh, direction: rising + Event: time: 1739063446763559386, type: accel(z), channel: 0, evty= pe: gesture, direction: singletap + Event: time: 1739063448818126480, type: accel(x&y&z), channel: 0, = evtype: thresh, direction: falling + ... + +Activity and inactivity belong together and indicate state changes as foll= ows + +.. code-block:: bash + + root:# iio_event_monitor adxl345 + Found IIO device with name adxl345 with device number 0 + Event: time: 1744648001133946293, type: accel(x), channel: 0, evty= pe: thresh, direction: rising + + Event: time: 1744648057724775499, type: accel(x&y&z), channel: 0, = evtype: thresh, direction: falling + ... + +3. Device Buffers +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +This driver supports IIO buffers. + +All devices support retrieving the raw acceleration and temperature measur= ements +using buffers. + +Usage examples +-------------- + +Select channels for buffer read: + +.. code-block:: bash + + root:/sys/bus/iio/devices/iio:device0> echo 1 > scan_elements/in_a= ccel_x_en + root:/sys/bus/iio/devices/iio:device0> echo 1 > scan_elements/in_a= ccel_y_en + root:/sys/bus/iio/devices/iio:device0> echo 1 > scan_elements/in_a= ccel_z_en + +Set the number of samples to be stored in the buffer: + +.. code-block:: bash + + root:/sys/bus/iio/devices/iio:device0> echo 10 > buffer/length + +Enable buffer readings: + +.. code-block:: bash + + root:/sys/bus/iio/devices/iio:device0> echo 1 > buffer/enable + +Obtain buffered data: + +.. code-block:: bash + + root:> iio_readdev -b 16 -s 1024 adxl345 | hexdump -d + WARNING: High-speed mode not enabled + 0000000 00003 00012 00013 00005 00010 00011 00005 = 00011 + 0000010 00013 00004 00012 00011 00003 00012 00014 = 00007 + 0000020 00011 00013 00004 00013 00014 00003 00012 = 00013 + 0000030 00004 00012 00013 00005 00011 00011 00005 = 00012 + 0000040 00014 00005 00012 00014 00004 00010 00012 = 00004 + 0000050 00013 00011 00003 00011 00012 00005 00011 = 00013 + 0000060 00003 00012 00012 00003 00012 00012 00004 = 00012 + 0000070 00012 00003 00013 00013 00003 00013 00012 = 00005 + 0000080 00012 00013 00003 00011 00012 00005 00012 = 00013 + 0000090 00003 00013 00011 00005 00013 00014 00003 = 00012 + 00000a0 00012 00003 00012 00013 00004 00012 00015 = 00004 + 00000b0 00014 00011 00003 00014 00013 00004 00012 = 00011 + 00000c0 00004 00012 00013 00004 00014 00011 00004 = 00013 + 00000d0 00012 00002 00014 00012 00005 00012 00013 = 00005 + 00000e0 00013 00013 00003 00013 00013 00005 00012 = 00013 + 00000f0 00004 00014 00015 00005 00012 00011 00005 = 00012 + ... + +See ``Documentation/iio/iio_devbuf.rst`` for more information about how bu= ffered +data is structured. + +4. IIO Interfacing Tools +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +See ``Documentation/iio/iio_tools.rst`` for the description of the availab= le IIO +interfacing tools. --=20 2.39.5