From patchwork Mon Apr 14 18:42:35 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lothar Rubusch X-Patchwork-Id: 14050875 Received: from mail-ej1-f42.google.com (mail-ej1-f42.google.com [209.85.218.42]) (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 B9E4D28BA85; Mon, 14 Apr 2025 18:42:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.42 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744656174; cv=none; b=Bph8sN6UruqCxX2Mgxr8yc5o2Oqs/AbfLT+DgrX1Q0JXhHNHOHO7u6po+SI0aF9Jlnw9Ym+GdpkWwfwnGhgn6wn1m2dxyuFdkzTH3qGx+OMVHva14YDTpzqtmu+YtTvHoo9t0v/HKOtGzjo26LRxMc1++Tab0Lv+UNFJciJoHYU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744656174; c=relaxed/simple; bh=fM3+KC/UZ31kXPGTb5S0rsSfrRmlbZY6btYAdurQouc=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=e21YUCE5BCGaCsvLNsaIZmKnmcYs/htphqkSMQov3KWR/wBvHu8ZBeT1/EUPgxBDEl4tuw2/2CuTzBiDwMrQ6L3SPrGmdXYUvHSHhDas3RvXnSioP/85lN47zFwS9Z1AWjox8BndgyJFo7UsaQPFdLwljCT4/rsf4fMSSFY1+Nc= 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=e2KmabLj; arc=none smtp.client-ip=209.85.218.42 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="e2KmabLj" Received: by mail-ej1-f42.google.com with SMTP id a640c23a62f3a-ac3f58b9156so57826166b.1; Mon, 14 Apr 2025 11:42:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1744656171; x=1745260971; 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=e2KmabLjVPcz75xXzzGsB3qBO3DzmsSaiFPOoF7Cf6uE/qg7oRBm5DLGpmZLky7cw/ Y/dzwHXnNJLmT/DS5VJ8iLfulTlGSxcskI+1eUQYSlS2RDDKmM+TkHqfDBQ0mxydvKE6 tn1BbVhK4n3Zsmou3JatmA5teHE+L1QGXsDvCOOCNGI7ffQltnGdA6P193O4lBNeak7W WZNfKSuKLRlJx36YCQeri1Vu1DM/2t52TZPVMOEf9XnI+Fnh6FP9ZRUJf3835ZYzKFOY 9Hzu3ObPJrIY02B7wORtwdQNsAVOX1t5CS4Lkapm9FkbfySet/ONvxaZQa89Z6/a4y8e NPpA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1744656171; x=1745260971; 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=qDBaNv0N6FARrCQV3hGPmBztWtZCR9497H8epwLS71VvctTPwhB6voHmla4/2yLPNH ta8z95/cGPt591mpEupy6fo+/uSw1g9QSHhlCLCmXU67+jvW4hU+j4RZqGKYArkAMPfO PKm1GIi+bTqlUACtODdSWyhlnqaftPX5uWbnW4Ocra9xCGfuWye8KKF6dY3Ytvz75YsU l/WPuUbfIAMDJKG67J+yXbLLy4KrfapCVTPcn2chSEHOOi/m/dnLmw5gXvT8xFs6k/Uq AuVj7A3pkCJQAmyHdGrKF7k5b0wbHjbXv6OyRxqHFGdqauy0I4Nsle4+71s5A8yz/mRA H4Ew== X-Forwarded-Encrypted: i=1; AJvYcCWT+12EY7TTgUzFKNW8oIvJjD0yWHXMfjsYVr3pM/hn5kW+ZYQ0CjvjPYuE8aQTlXU6K+xRLiUVIRDjaEo=@vger.kernel.org X-Gm-Message-State: AOJu0Yw3QiUJUnAdBaYI96cbHEnYM/sLSU8hoRBKo39TOGLPFoHIZCxf qOhlVFUc5L7vvRWuNPW1CHRTKA+xim//2oFmNJMn5XnjXIGbrv/B X-Gm-Gg: ASbGncuCp1Zt1Uw9zBSC73yMkoz/zQIqf4fk6K6sbRdPxZ85+Bb4srLDoSoulqZqcKD vvevWhvoCXyWRI5XJqOiD6mfKziBebq0s7TEE4O75iQIoh4tZQvDf4N4NsJgKikg8sZ8DCuAjdH duLMBlY0HRCpoWe7YsOZpV9T1PjZM6rYHACMN0iRaVSf/FIF1pn344X8EizKK8J9TkBKi35vFy8 av4+Af+4lRzVDrbaxS2qUhmXOm3oDcog5kPoK7OzTODH6ONTM2+XMfL8B/ggEkVKJ1GtkJ9ZdV3 MQkBK6BTQqFt/ci6FhA3wV7KOaHmDl51g6LE/9GeGhokK3kekAZN7B/oYWeqmlXkCF7DH8ndnnr OvVk16pgEklyngUI1K6LudxMdZTOaBQ== X-Google-Smtp-Source: AGHT+IGFOPrgXPclowiGFYIQKb812Qh2MFB6TP+Vy9uyAexDlY8mHJLLmm0XlxO0VSkg0mlGaPssHA== X-Received: by 2002:a17:907:db08:b0:ac7:3910:16ad with SMTP id a640c23a62f3a-acad36db7c9mr406154566b.16.1744656170581; Mon, 14 Apr 2025 11:42:50 -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-acaa1bb3172sm946483466b.24.2025.04.14.11.42.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 14 Apr 2025 11:42:50 -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 v6 01/11] iio: accel: adxl345: introduce adxl345_push_event function Date: Mon, 14 Apr 2025 18:42:35 +0000 Message-Id: <20250414184245.100280-2-l.rubusch@gmail.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250414184245.100280-1-l.rubusch@gmail.com> References: <20250414184245.100280-1-l.rubusch@gmail.com> Precedence: bulk X-Mailing-List: linux-iio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Move the fifo handling into a separate function. This is a preparation for a generic handling of the interrupt status register results. The function is supposed to handle particular sensor events, and later to forward them to the iio channel. This is needed to read out the interrupt status register. The function shall return occurring errors, if any, or 0 in case of handled events or read fifo content. Thus migrate fifo read-out and push fifo content to iio channels into this function to be built up with additional event handling. Signed-off-by: Lothar Rubusch --- drivers/iio/accel/adxl345_core.c | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/drivers/iio/accel/adxl345_core.c b/drivers/iio/accel/adxl345_core.c index 1b4d9e60c87d..a98fb7fc748e 100644 --- a/drivers/iio/accel/adxl345_core.c +++ b/drivers/iio/accel/adxl345_core.c @@ -416,6 +416,23 @@ static int adxl345_fifo_push(struct iio_dev *indio_dev, return 0; } +static int adxl345_push_event(struct iio_dev *indio_dev, int int_stat) +{ + struct adxl345_state *st = iio_priv(indio_dev); + int samples; + + if (FIELD_GET(ADXL345_INT_WATERMARK, int_stat)) { + samples = adxl345_get_samples(st); + if (samples < 0) + return -EINVAL; + + if (adxl345_fifo_push(indio_dev, samples) < 0) + return -EINVAL; + } + + return 0; +} + /** * adxl345_irq_handler() - Handle irqs of the ADXL345. * @irq: The irq being handled. @@ -428,19 +445,12 @@ static irqreturn_t adxl345_irq_handler(int irq, void *p) struct iio_dev *indio_dev = p; struct adxl345_state *st = iio_priv(indio_dev); int int_stat; - int samples; if (regmap_read(st->regmap, ADXL345_REG_INT_SOURCE, &int_stat)) return IRQ_NONE; - if (FIELD_GET(ADXL345_INT_WATERMARK, int_stat)) { - samples = adxl345_get_samples(st); - if (samples < 0) - goto err; - - if (adxl345_fifo_push(indio_dev, samples) < 0) - goto err; - } + if (adxl345_push_event(indio_dev, int_stat)) + goto err; if (FIELD_GET(ADXL345_INT_OVERRUN, int_stat)) goto err; From patchwork Mon Apr 14 18:42:36 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lothar Rubusch X-Patchwork-Id: 14050876 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 9026C156236; Mon, 14 Apr 2025 18:42:53 +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=1744656175; cv=none; b=gjIaIF0PZHi/1mtNw4AChTtBhSgnuxMqGnZSUIw+BLeUsH8KSZ8L+XMZKcuupSXoYydHp+kw7OLpL3UmmiFhpVLF/dz74mxFRXaS56RLBC5PwAM3NTFez8LL5Obx1YENe8UuZmDT0amA9FrP/1jwqLCy+Mt80QpF0PQ1sAa7VLk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744656175; c=relaxed/simple; bh=5RxrPYtZ7I6Dt5qarm4tttwb4MttmZTzMw61EXrH4Qc=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=kAYgmy/WyrxoJuBU4Vunko4Le7W9iW18ScMronHxHTRFXZnY5BeGaPalWdWMQWSf2NGfcaNVJ4ZG1sKxLEGjPnIPI/6rOrfb1Aki7lVwCNSAQpBIdUyFnOTtEmf3QrO4s9TBlsEaikpLyAXy1CFkkwAOH5/BsATrT6ZMNdSGIS0= 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=K5lPklgq; 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="K5lPklgq" Received: by mail-ej1-f45.google.com with SMTP id a640c23a62f3a-ac2c7a36802so85358366b.2; Mon, 14 Apr 2025 11:42:53 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1744656172; x=1745260972; 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=K5lPklgqX+DFB//9nImfo2sg9nzcRFRnZpgAOKS275y9Np6xjtqtuT+uurindTKM6J 2GvEjlx2v7tP9BRur2wyXkl+YwoU7LuMoeJ91nX3J+/FDuXNNfRhdT+KMg309+XpPscs /bEv4JCmW3S2VQaz/yxalYAaFHK2wR/M5HoSdReRo+t8ItFwG+7QJt9fUUagVXXeOHxG cteFBmffPCIPH7bUaNwzxjLkGLa9EncJW3LNez7vPMombfLsuElt6odIOwDRiV7FkSuR zwtSXi1it+8EF5ILivxWPelf0MwXT8wvKg+fWnfwvZW0EFCNEmmxvXZH5SyQqWjBjcQk DOlw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1744656172; x=1745260972; 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=KrlHmq2PDVoYx80qLgRVZ7hZ2z/X+cx+rVaFCKgmZ2pMcADqsyDHwKYkk+Bx64iLm0 /YBf7oXkJ1khCg2KabrJcd3nTPmrmxVPMMKCUKcObTkX6427Vhrg8PVJyfgfIh9ZI2zx 1JngWUh5sQh/iqVnfEob7fIr3YJclKWOWb+yCE5G9tYv/YJ8xnl0CAdPFNpdlrW/ITx3 3n0QwCk01RKqgqcMiMhu2fuGBlMlmVt6gjoJNRBPXeM1tB7FpsF0YWeZXuPk23Oka02T XzJ2UhncAxfdxlwLsicqH0fe5X+yguzPhst9567+Jnr8OY/jNHIKDUy+3MzXigiGvRCH Lntg== X-Forwarded-Encrypted: i=1; AJvYcCXa+M55uGNmhzCwgpo+NScHzo6EKRPF+jDnpk10hdFJ1BNcsLh+Etqf++XhoXWL5EuxtJw4aCYRKvTeyK8=@vger.kernel.org X-Gm-Message-State: AOJu0YzWMsdvXBzGKG3ly4COwBZJR9pt5iUbJ5rYpGwFxxWovdGGGmAE n6JnRHsCU6P2huv9SU846WOSXgh6iNhgQ/B0Yq+cVGtOtzjD5G0o X-Gm-Gg: ASbGncvkE9Mk9FbntOtYomqP9vvM/GPfvApyEM9+tCFRhuoSyYM8s30CqkYqbPLpSfm kQiB4lDIVKWziTBqm4180KVyheDecoi356v1QNJVahNrI9Ao6/aTspKVXLocNZbyCMVw2Fr+pIh SlIQheR1FIqEAt50ql85L/8kLA3XDIPD/nAgyVMR6ciTNbgpruRCVootU6TDtGOZkPhAcof+Gzw 8QGfjtVErK54oW/HcRya5/NEHzHC8ahV9YG3+quEf7YDllG4eCHdNFURFvhqg6ui9hID8HXbssj ofO3lGmSnU80eOKbfi74fJy6mPQ93iDwaFs3TVD0xVP5EYaGlyYwCRS50bn90MAurvyYc3s01m4 /32aMb1c6gMIUehrPWrk= X-Google-Smtp-Source: AGHT+IFayrictClLxvWNwCsh0gJp3btoMn1UzriyLE71QmzMois11lWSPynzRqW4jKoUJtT5c5+KdQ== X-Received: by 2002:a17:907:c8a8:b0:ac4:4c2:e8c7 with SMTP id a640c23a62f3a-acad36a1d86mr423144466b.12.1744656171567; Mon, 14 Apr 2025 11:42:51 -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-acaa1bb3172sm946483466b.24.2025.04.14.11.42.50 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 14 Apr 2025 11:42:51 -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 v6 02/11] iio: accel: adxl345: add single tap feature Date: Mon, 14 Apr 2025 18:42:36 +0000 Message-Id: <20250414184245.100280-3-l.rubusch@gmail.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250414184245.100280-1-l.rubusch@gmail.com> References: <20250414184245.100280-1-l.rubusch@gmail.com> Precedence: bulk X-Mailing-List: linux-iio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Add the single tap feature with a threshold in 62.5mg/LSB points and a scaled duration in us. Keep singletap threshold in regmap cache but the scaled value of duration in us as member variable. Both use IIO channels for individual enable of the x/y/z axis. Initializes threshold and duration with reasonable content. When an interrupt is caught it will be pushed to the according IIO channel. Signed-off-by: Lothar Rubusch --- drivers/iio/accel/adxl345_core.c | 372 ++++++++++++++++++++++++++++++- 1 file changed, 369 insertions(+), 3 deletions(-) diff --git a/drivers/iio/accel/adxl345_core.c b/drivers/iio/accel/adxl345_core.c index a98fb7fc748e..ccb25c35ac07 100644 --- a/drivers/iio/accel/adxl345_core.c +++ b/drivers/iio/accel/adxl345_core.c @@ -8,6 +8,7 @@ */ #include +#include #include #include #include @@ -17,6 +18,7 @@ #include #include #include +#include #include #include "adxl345.h" @@ -31,6 +33,29 @@ #define ADXL345_INT1 0 #define ADXL345_INT2 1 +#define ADXL345_REG_TAP_AXIS_MSK GENMASK(2, 0) + +#define ADXL345_TAP_Z_EN BIT(0) +#define ADXL345_TAP_Y_EN BIT(1) +#define ADXL345_TAP_X_EN BIT(2) + +/* single/double tap */ +enum adxl345_tap_type { + ADXL345_SINGLE_TAP, +}; + +static const unsigned int adxl345_tap_int_reg[] = { + [ADXL345_SINGLE_TAP] = ADXL345_INT_SINGLE_TAP, +}; + +enum adxl345_tap_time_type { + ADXL345_TAP_TIME_DUR, +}; + +static const unsigned int adxl345_tap_time_reg[] = { + [ADXL345_TAP_TIME_DUR] = ADXL345_REG_DUR, +}; + struct adxl345_state { const struct adxl345_chip_info *info; struct regmap *regmap; @@ -38,9 +63,23 @@ struct adxl345_state { int irq; u8 watermark; u8 fifo_mode; + + u32 tap_duration_us; + __le16 fifo_buf[ADXL345_DIRS * ADXL345_FIFO_SIZE + 1] __aligned(IIO_DMA_MINALIGN); }; +static struct iio_event_spec adxl345_events[] = { + { + /* single tap */ + .type = IIO_EV_TYPE_GESTURE, + .dir = IIO_EV_DIR_SINGLETAP, + .mask_separate = BIT(IIO_EV_INFO_ENABLE), + .mask_shared_by_type = BIT(IIO_EV_INFO_VALUE) | + BIT(IIO_EV_INFO_TIMEOUT), + }, +}; + #define ADXL345_CHANNEL(index, reg, axis) { \ .type = IIO_ACCEL, \ .modified = 1, \ @@ -57,6 +96,8 @@ struct adxl345_state { .storagebits = 16, \ .endianness = IIO_LE, \ }, \ + .event_spec = adxl345_events, \ + .num_event_specs = ARRAY_SIZE(adxl345_events), \ } enum adxl345_chans { @@ -113,6 +154,157 @@ static int adxl345_set_measure_en(struct adxl345_state *st, bool en) return regmap_write(st->regmap, ADXL345_REG_POWER_CTL, val); } +/* tap */ + +static int _adxl345_set_tap_int(struct adxl345_state *st, + enum adxl345_tap_type type, bool state) +{ + unsigned int int_map = 0x00; + unsigned int tap_threshold; + bool axis_valid; + bool singletap_args_valid = false; + bool en = false; + u32 axis_ctrl; + int ret; + + ret = regmap_read(st->regmap, ADXL345_REG_TAP_AXIS, &axis_ctrl); + if (ret) + return ret; + + axis_valid = FIELD_GET(ADXL345_REG_TAP_AXIS_MSK, axis_ctrl) > 0; + + ret = regmap_read(st->regmap, ADXL345_REG_THRESH_TAP, &tap_threshold); + if (ret) + return ret; + + /* + * Note: A value of 0 for threshold and/or dur may result in undesirable + * behavior if single tap/double tap interrupts are enabled. + */ + singletap_args_valid = tap_threshold > 0 && st->tap_duration_us > 0; + + if (type == ADXL345_SINGLE_TAP) + en = axis_valid && singletap_args_valid; + + if (state && en) + int_map |= adxl345_tap_int_reg[type]; + + return regmap_update_bits(st->regmap, ADXL345_REG_INT_ENABLE, + adxl345_tap_int_reg[type], int_map); +} + +static int adxl345_is_tap_en(struct adxl345_state *st, + enum iio_modifier axis, + enum adxl345_tap_type type, bool *en) +{ + unsigned int regval; + u32 axis_ctrl; + int ret; + + ret = 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 = FIELD_GET(ADXL345_TAP_X_EN, axis_ctrl); + break; + case IIO_MOD_Y: + *en = FIELD_GET(ADXL345_TAP_Y_EN, axis_ctrl); + break; + case IIO_MOD_Z: + *en = FIELD_GET(ADXL345_TAP_Z_EN, axis_ctrl); + break; + default: + *en = false; + return -EINVAL; + } + + if (*en) { + /* + * If axis allow for tap detection, verify if the interrupt is + * enabled for tap detection. + */ + ret = regmap_read(st->regmap, ADXL345_REG_INT_ENABLE, ®val); + if (ret) + return ret; + + *en = 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 = ADXL345_TAP_X_EN; + break; + case IIO_MOD_Y: + axis_ctrl = ADXL345_TAP_Y_EN; + break; + case IIO_MOD_Z: + axis_ctrl = ADXL345_TAP_Z_EN; + break; + default: + return -EINVAL; + } + + if (en) + ret = regmap_set_bits(st->regmap, ADXL345_REG_TAP_AXIS, + axis_ctrl); + else + ret = regmap_clear_bits(st->regmap, ADXL345_REG_TAP_AXIS, + axis_ctrl); + if (ret) + return ret; + + return _adxl345_set_tap_int(st, ADXL345_SINGLE_TAP, en); +} + +static int _adxl345_set_tap_time(struct adxl345_state *st, + enum adxl345_tap_time_type type, u32 val_us) +{ + unsigned int regval; + + switch (type) { + case ADXL345_TAP_TIME_DUR: + st->tap_duration_us = val_us; + break; + } + + /* + * The scale factor is 1250us / LSB for tap_window_us and tap_latent_us. + * For tap_duration_us the scale factor is 625us / LSB. + */ + if (type == ADXL345_TAP_TIME_DUR) + regval = DIV_ROUND_CLOSEST(val_us, 625); + else + regval = DIV_ROUND_CLOSEST(val_us, 1250); + + return regmap_write(st->regmap, adxl345_tap_time_reg[type], regval); +} + +static int adxl345_set_tap_duration(struct adxl345_state *st, u32 val_int, + u32 val_fract_us) +{ + /* + * Max value is 255 * 625 us = 0.159375 seconds + * + * Note: the scaling is similar to the scaling in the ADXL380 + */ + if (val_int || val_fract_us > 159375) + return -EINVAL; + + return _adxl345_set_tap_time(st, ADXL345_TAP_TIME_DUR, val_fract_us); +} + static int adxl345_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask) @@ -198,6 +390,131 @@ static int adxl345_write_raw(struct iio_dev *indio_dev, return -EINVAL; } +static int adxl345_read_event_config(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir) +{ + struct adxl345_state *st = iio_priv(indio_dev); + bool int_en; + int ret; + + switch (type) { + case IIO_EV_TYPE_GESTURE: + switch (dir) { + case IIO_EV_DIR_SINGLETAP: + ret = adxl345_is_tap_en(st, chan->channel2, + ADXL345_SINGLE_TAP, &int_en); + if (ret) + return ret; + return int_en; + default: + return -EINVAL; + } + default: + return -EINVAL; + } +} + +static int adxl345_write_event_config(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + bool state) +{ + struct adxl345_state *st = iio_priv(indio_dev); + + switch (type) { + case IIO_EV_TYPE_GESTURE: + switch (dir) { + case IIO_EV_DIR_SINGLETAP: + return adxl345_set_singletap_en(st, chan->channel2, state); + default: + return -EINVAL; + } + default: + return -EINVAL; + } +} + +static int adxl345_read_event_value(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + enum iio_event_info info, + int *val, int *val2) +{ + struct adxl345_state *st = iio_priv(indio_dev); + unsigned int tap_threshold; + int ret; + + switch (type) { + case IIO_EV_TYPE_GESTURE: + switch (info) { + case IIO_EV_INFO_VALUE: + /* + * The scale factor would be 62.5mg/LSB (i.e. 0xFF = 16g) but + * not applied here. In context of this general purpose sensor, + * what imports is rather signal intensity than the absolute + * measured g value. + */ + ret = regmap_read(st->regmap, ADXL345_REG_THRESH_TAP, + &tap_threshold); + if (ret) + return ret; + *val = sign_extend32(tap_threshold, 7); + return IIO_VAL_INT; + case IIO_EV_INFO_TIMEOUT: + *val = st->tap_duration_us; + *val2 = 1000000; + return IIO_VAL_FRACTIONAL; + default: + return -EINVAL; + } + default: + return -EINVAL; + } +} + +static int adxl345_write_event_value(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + enum iio_event_info info, + int val, int val2) +{ + struct adxl345_state *st = iio_priv(indio_dev); + int ret; + + ret = adxl345_set_measure_en(st, false); + if (ret) + return ret; + + switch (type) { + case IIO_EV_TYPE_GESTURE: + switch (info) { + case IIO_EV_INFO_VALUE: + ret = regmap_write(st->regmap, ADXL345_REG_THRESH_TAP, + min(val, 0xFF)); + if (ret) + return ret; + break; + case IIO_EV_INFO_TIMEOUT: + ret = adxl345_set_tap_duration(st, val, val2); + if (ret) + return ret; + break; + default: + return -EINVAL; + } + break; + default: + return -EINVAL; + } + + return adxl345_set_measure_en(st, true); +} + static int adxl345_reg_access(struct iio_dev *indio_dev, unsigned int reg, unsigned int writeval, unsigned int *readval) { @@ -416,10 +733,23 @@ static int adxl345_fifo_push(struct iio_dev *indio_dev, return 0; } -static int adxl345_push_event(struct iio_dev *indio_dev, int int_stat) +static int adxl345_push_event(struct iio_dev *indio_dev, int int_stat, + enum iio_modifier tap_dir) { + s64 ts = iio_get_time_ns(indio_dev); struct adxl345_state *st = iio_priv(indio_dev); int samples; + int ret = -ENOENT; + + if (FIELD_GET(ADXL345_INT_SINGLE_TAP, int_stat)) { + ret = iio_push_event(indio_dev, + IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, tap_dir, + IIO_EV_TYPE_GESTURE, + IIO_EV_DIR_SINGLETAP), + ts); + if (ret) + return ret; + } if (FIELD_GET(ADXL345_INT_WATERMARK, int_stat)) { samples = adxl345_get_samples(st); @@ -428,9 +758,11 @@ static int adxl345_push_event(struct iio_dev *indio_dev, int int_stat) if (adxl345_fifo_push(indio_dev, samples) < 0) return -EINVAL; + + ret = 0; } - return 0; + return ret; } /** @@ -444,12 +776,33 @@ static irqreturn_t adxl345_irq_handler(int irq, void *p) { struct iio_dev *indio_dev = p; struct adxl345_state *st = iio_priv(indio_dev); + unsigned int regval; + enum iio_modifier tap_dir = IIO_NO_MOD; + u32 axis_ctrl; int int_stat; + int ret; + + ret = regmap_read(st->regmap, ADXL345_REG_TAP_AXIS, &axis_ctrl); + if (ret) + return IRQ_NONE; + + if (FIELD_GET(ADXL345_REG_TAP_AXIS_MSK, axis_ctrl)) { + ret = regmap_read(st->regmap, ADXL345_REG_ACT_TAP_STATUS, ®val); + if (ret) + return IRQ_NONE; + + if (FIELD_GET(ADXL345_TAP_Z_EN, regval)) + tap_dir = IIO_MOD_Z; + else if (FIELD_GET(ADXL345_TAP_Y_EN, regval)) + tap_dir = IIO_MOD_Y; + else if (FIELD_GET(ADXL345_TAP_X_EN, regval)) + tap_dir = IIO_MOD_X; + } if (regmap_read(st->regmap, ADXL345_REG_INT_SOURCE, &int_stat)) return IRQ_NONE; - if (adxl345_push_event(indio_dev, int_stat)) + if (adxl345_push_event(indio_dev, int_stat, tap_dir)) goto err; if (FIELD_GET(ADXL345_INT_OVERRUN, int_stat)) @@ -468,6 +821,10 @@ static const struct iio_info adxl345_info = { .read_raw = adxl345_read_raw, .write_raw = adxl345_write_raw, .write_raw_get_fmt = adxl345_write_raw_get_fmt, + .read_event_config = adxl345_read_event_config, + .write_event_config = adxl345_write_event_config, + .read_event_value = adxl345_read_event_value, + .write_event_value = adxl345_write_event_value, .debugfs_reg_access = &adxl345_reg_access, .hwfifo_set_watermark = adxl345_set_watermark, }; @@ -501,6 +858,7 @@ int adxl345_core_probe(struct device *dev, struct regmap *regmap, ADXL345_DATA_FORMAT_JUSTIFY | ADXL345_DATA_FORMAT_FULL_RES | ADXL345_DATA_FORMAT_SELF_TEST); + unsigned int tap_threshold; int ret; indio_dev = devm_iio_device_alloc(dev, sizeof(*st)); @@ -514,6 +872,10 @@ int adxl345_core_probe(struct device *dev, struct regmap *regmap, return -ENODEV; st->fifo_delay = fifo_delay_default; + /* Init with reasonable values */ + tap_threshold = 48; /* 48 [0x30] -> ~3g */ + st->tap_duration_us = 16; /* 16 [0x10] -> .010 */ + indio_dev->name = st->info->name; indio_dev->info = &adxl345_info; indio_dev->modes = INDIO_DIRECT_MODE; @@ -586,6 +948,10 @@ int adxl345_core_probe(struct device *dev, struct regmap *regmap, if (ret) return ret; + ret = regmap_write(st->regmap, ADXL345_REG_THRESH_TAP, tap_threshold); + if (ret) + return ret; + /* FIFO_STREAM mode is going to be activated later */ ret = devm_iio_kfifo_buffer_setup(dev, indio_dev, &adxl345_buffer_ops); if (ret) From patchwork Mon Apr 14 18:42:37 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lothar Rubusch X-Patchwork-Id: 14050877 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 AF9E1289340; Mon, 14 Apr 2025 18:42:54 +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=1744656176; cv=none; b=Er3d87cg2IYe4pBCOwPR1+NuPAdiQ/jthsPyrwbxbJMKA8wPn1/76rdi2he18pT4RYZogjj0rA4SvXR88urAly0YV0xjtbZiU6/9weaRnuiPbpmn3ShXYgl14RTT307wETYL+PtN0tzPxbMt8caYHM3Meuio6tCOYae23ACWvQE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744656176; c=relaxed/simple; bh=0CGAbwxTgGMgGM/mr6uEkMLoVL7t36cFFW8BH3LDQe4=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=kuS7zttrajmUANqruTS18HLRR23m2BFWHEAI0e0jxHg1xMkQT86fuaD6Sa4BVLSAY8Y8zL6akmNnKg6pEdAxDHpUo/oYR95mKMVijbu0eH96FRVlUpNSwrtmkiVZV8PqbtHPmxcYSubf6LttHN9aegwFDt46fPewXdvXQiYMYcw= 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=T0RLJZRm; 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="T0RLJZRm" Received: by mail-ej1-f46.google.com with SMTP id a640c23a62f3a-ab7098af6fdso90460766b.2; Mon, 14 Apr 2025 11:42:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1744656173; x=1745260973; 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=T0RLJZRmcjMo+iWITe5goQqRIT5MAlDnV9b/g1aKAFcH+ZYgc5xcyBNJS9EMDWkm3R vfyt0HF9Jm/YBO1tlp1wgx7VMfB/wFiSPHhi5LnxfAcf+Wbgg9rH10wHv3hFE00YB6E3 t+xiKVcs0Dm5DbiwWB8D9kSHVDPxM8+yHu2RWuJeU2aNSPUUCwdgbqMpMf6x3Ri0qLXp xQrVpgxOuydanmrNeFmg7iyzYnpXZmTePfkHHW/vjvvqJchQZm+Mc0oQm1p0w3o+HJyi FxD/6gCEf/bAZOPJbhF7EDbRCZ1OctKXabXa025Fir0McnlKVsEBiaQ8k10hnHgtTZs7 T99w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1744656173; x=1745260973; 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=Xwx1H/aAOod7oZqo05WgS//b6uyGPGLt57ietQGMY+eL4WKtBQEiwvZwkjK4B+75gW SFj0FCf+hFtMwKU4bNXeulpdoVmwSqeiG2N3z/0oWZf2lfkD/S4raejXYcNBGax/X6Nu f1jPX3Jc6R0Ibi0/AeXHfZm+2jblKGy4kE51ae+9O6aAou5GF6e85rJXuQflDdCIc4XA aBnQXsMsH1plnXTfOZoadHzPp4Uhqzbw8bMQ/g2vuhcHkROMSu12aUcelm0as09pVKMN qPL1zmp5Uvsn2JXaAuDpW6v5Fj6HPVD5g8752uo0pero8YKsVo016RgIfpvfI51WCoK9 oF6g== X-Forwarded-Encrypted: i=1; AJvYcCU3ibfcSflwzm+GyqK7usMgkyhuehaMebMYJlhYFuYOn6SzVQyAytpbr3N0YxNfQWVhSs/Kz8QO3jw/kOc=@vger.kernel.org X-Gm-Message-State: AOJu0YxF+kCkBo3NHa8Bz6QknFdYbWBYgP0RGs3e9gbL8fDijP+ta/8x SFIR9hFgs4gM3l8qN8/X8OwpkNMqpJ4PaXIhJwVC53x2vgayEfvF X-Gm-Gg: ASbGncsODhZ//CkG8KWF+7ccePxkjs9CFgMGTiiiEw4KmWUjwcOu7KhmKk3Dx466yYA /SXfp0ymkKz7IQWmU9ogvEJm0XFWxt3S95kRmcKBjNgV4UrqwEaQq7oLIoa6LqGM1U26hWbNjhI GCtk5bV2IyjRr170ccgR664VoKOmEq6iW2HcIHMQYqxqNg7HCBSC7IZVnYSLT7re7D8nguA84hz 9jbv0wj2gbur1zpcHVqjquCfawuA9MLjsOcFfPNoOWlSX2gu3sy8eCkfbEyvdinJBJ7XtYVC6I1 y/R6QEs6ANXJm3hT2oQoctfbxlyGcHdDmKGN0Ixaz03fgpSUfsXwJviAlOu3hxp4lGycA2AyDxe WkSBi/rxNUcxAgwf65bc= X-Google-Smtp-Source: AGHT+IGcsvw/qwjnmAOjtLptABi143w/CE5RFQ2t1nxY8HYE3Ilxxpx4rSvZ7T8+XGeGGmISwuQCyg== X-Received: by 2002:a17:907:9593:b0:ac7:9237:60a8 with SMTP id a640c23a62f3a-acb13da62fdmr24065666b.9.1744656172507; Mon, 14 Apr 2025 11:42:52 -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-acaa1bb3172sm946483466b.24.2025.04.14.11.42.51 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 14 Apr 2025 11:42:52 -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 v6 03/11] iio: accel: adxl345: add double tap feature Date: Mon, 14 Apr 2025 18:42:37 +0000 Message-Id: <20250414184245.100280-4-l.rubusch@gmail.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250414184245.100280-1-l.rubusch@gmail.com> References: <20250414184245.100280-1-l.rubusch@gmail.com> Precedence: bulk X-Mailing-List: linux-iio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Add the double tap feature of the sensor. The interrupt handler needs to catch and forward the event to the IIO channel. The single tap implementation now is extended to deal with double tap as well. Doubletap introduces window and latency times, both in us. Since both times are scaled, the 8-bit register value is stored in hardware, where the scaled value in [us] is stored as member variable. Signed-off-by: Lothar Rubusch --- drivers/iio/accel/adxl345_core.c | 104 ++++++++++++++++++++++++++++++- 1 file changed, 103 insertions(+), 1 deletion(-) diff --git a/drivers/iio/accel/adxl345_core.c b/drivers/iio/accel/adxl345_core.c index 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, }; static const unsigned int adxl345_tap_int_reg[] = { [ADXL345_SINGLE_TAP] = ADXL345_INT_SINGLE_TAP, + [ADXL345_DOUBLE_TAP] = ADXL345_INT_DOUBLE_TAP, }; enum adxl345_tap_time_type { + ADXL345_TAP_TIME_LATENT, + ADXL345_TAP_TIME_WINDOW, ADXL345_TAP_TIME_DUR, }; static const unsigned int adxl345_tap_time_reg[] = { + [ADXL345_TAP_TIME_LATENT] = ADXL345_REG_LATENT, + [ADXL345_TAP_TIME_WINDOW] = ADXL345_REG_WINDOW, [ADXL345_TAP_TIME_DUR] = ADXL345_REG_DUR, }; @@ -65,6 +71,8 @@ struct adxl345_state { u8 fifo_mode; u32 tap_duration_us; + u32 tap_latent_us; + u32 tap_window_us; __le16 fifo_buf[ADXL345_DIRS * ADXL345_FIFO_SIZE + 1] __aligned(IIO_DMA_MINALIGN); }; @@ -78,6 +86,14 @@ static struct iio_event_spec adxl345_events[] = { .mask_shared_by_type = BIT(IIO_EV_INFO_VALUE) | BIT(IIO_EV_INFO_TIMEOUT), }, + { + /* double tap */ + .type = IIO_EV_TYPE_GESTURE, + .dir = IIO_EV_DIR_DOUBLETAP, + .mask_shared_by_type = BIT(IIO_EV_INFO_ENABLE) | + BIT(IIO_EV_INFO_RESET_TIMEOUT) | + BIT(IIO_EV_INFO_TAP2_MIN_DELAY), + }, }; #define ADXL345_CHANNEL(index, reg, axis) { \ @@ -163,6 +179,7 @@ static int _adxl345_set_tap_int(struct adxl345_state *st, unsigned int tap_threshold; bool axis_valid; bool singletap_args_valid = false; + bool doubletap_args_valid = false; bool en = false; u32 axis_ctrl; int ret; @@ -183,8 +200,16 @@ static int _adxl345_set_tap_int(struct adxl345_state *st, */ singletap_args_valid = tap_threshold > 0 && st->tap_duration_us > 0; - if (type == ADXL345_SINGLE_TAP) + if (type == ADXL345_SINGLE_TAP) { en = axis_valid && singletap_args_valid; + } else { + /* doubletap: Window must be equal or greater than latent! */ + doubletap_args_valid = st->tap_latent_us > 0 && + st->tap_window_us > 0 && + st->tap_window_us >= st->tap_latent_us; + + en = axis_valid && singletap_args_valid && doubletap_args_valid; + } if (state && en) int_map |= adxl345_tap_int_reg[type]; @@ -268,12 +293,23 @@ static int adxl345_set_singletap_en(struct adxl345_state *st, return _adxl345_set_tap_int(st, ADXL345_SINGLE_TAP, en); } +static int adxl345_set_doubletap_en(struct adxl345_state *st, bool en) +{ + return _adxl345_set_tap_int(st, ADXL345_DOUBLE_TAP, en); +} + static int _adxl345_set_tap_time(struct adxl345_state *st, enum adxl345_tap_time_type type, u32 val_us) { unsigned int regval; switch (type) { + case ADXL345_TAP_TIME_WINDOW: + st->tap_window_us = val_us; + break; + case ADXL345_TAP_TIME_LATENT: + st->tap_latent_us = val_us; + break; case ADXL345_TAP_TIME_DUR: st->tap_duration_us = val_us; break; @@ -305,6 +341,34 @@ static int adxl345_set_tap_duration(struct adxl345_state *st, u32 val_int, return _adxl345_set_tap_time(st, ADXL345_TAP_TIME_DUR, val_fract_us); } +static int adxl345_set_tap_window(struct adxl345_state *st, u32 val_int, + u32 val_fract_us) +{ + /* + * Max value is 255 * 1250 us = 0.318750 seconds + * + * Note: the scaling is similar to the scaling in the ADXL380 + */ + if (val_int || val_fract_us > 318750) + return -EINVAL; + + return _adxl345_set_tap_time(st, ADXL345_TAP_TIME_WINDOW, val_fract_us); +} + +static int adxl345_set_tap_latent(struct adxl345_state *st, u32 val_int, + u32 val_fract_us) +{ + /* + * Max value is 255 * 1250 us = 0.318750 seconds + * + * Note: the scaling is similar to the scaling in the ADXL380 + */ + if (val_int || val_fract_us > 318750) + return -EINVAL; + + return _adxl345_set_tap_time(st, ADXL345_TAP_TIME_LATENT, val_fract_us); +} + static int adxl345_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask) @@ -408,6 +472,12 @@ static int adxl345_read_event_config(struct iio_dev *indio_dev, if (ret) return ret; return int_en; + case IIO_EV_DIR_DOUBLETAP: + ret = adxl345_is_tap_en(st, chan->channel2, + ADXL345_DOUBLE_TAP, &int_en); + if (ret) + return ret; + return int_en; default: return -EINVAL; } @@ -429,6 +499,8 @@ static int adxl345_write_event_config(struct iio_dev *indio_dev, switch (dir) { case IIO_EV_DIR_SINGLETAP: return adxl345_set_singletap_en(st, chan->channel2, state); + case IIO_EV_DIR_DOUBLETAP: + return adxl345_set_doubletap_en(st, state); default: return -EINVAL; } @@ -468,6 +540,14 @@ static int adxl345_read_event_value(struct iio_dev *indio_dev, *val = st->tap_duration_us; *val2 = 1000000; return IIO_VAL_FRACTIONAL; + case IIO_EV_INFO_RESET_TIMEOUT: + *val = st->tap_window_us; + *val2 = 1000000; + return IIO_VAL_FRACTIONAL; + case IIO_EV_INFO_TAP2_MIN_DELAY: + *val = st->tap_latent_us; + *val2 = 1000000; + return IIO_VAL_FRACTIONAL; default: return -EINVAL; } @@ -504,6 +584,16 @@ static int adxl345_write_event_value(struct iio_dev *indio_dev, if (ret) return ret; break; + case IIO_EV_INFO_RESET_TIMEOUT: + ret = adxl345_set_tap_window(st, val, val2); + if (ret) + return ret; + break; + case IIO_EV_INFO_TAP2_MIN_DELAY: + ret = adxl345_set_tap_latent(st, val, val2); + if (ret) + return ret; + break; default: return -EINVAL; } @@ -751,6 +841,16 @@ static int adxl345_push_event(struct iio_dev *indio_dev, int int_stat, return ret; } + if (FIELD_GET(ADXL345_INT_DOUBLE_TAP, int_stat)) { + ret = iio_push_event(indio_dev, + IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, tap_dir, + IIO_EV_TYPE_GESTURE, + IIO_EV_DIR_DOUBLETAP), + ts); + if (ret) + return ret; + } + if (FIELD_GET(ADXL345_INT_WATERMARK, int_stat)) { samples = adxl345_get_samples(st); if (samples < 0) @@ -875,6 +975,8 @@ int adxl345_core_probe(struct device *dev, struct regmap *regmap, /* Init with reasonable values */ tap_threshold = 48; /* 48 [0x30] -> ~3g */ st->tap_duration_us = 16; /* 16 [0x10] -> .010 */ + st->tap_window_us = 64; /* 64 [0x40] -> .080 */ + st->tap_latent_us = 16; /* 16 [0x10] -> .020 */ indio_dev->name = st->info->name; indio_dev->info = &adxl345_info; From patchwork Mon Apr 14 18:42:38 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lothar Rubusch X-Patchwork-Id: 14050878 Received: from mail-ej1-f42.google.com (mail-ej1-f42.google.com [209.85.218.42]) (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 7A4F528DEE9; Mon, 14 Apr 2025 18:42:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.42 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744656177; cv=none; b=NfO/r4soRh0mE9OrOFr2w0Xd6KgqP5fQmnx0MjzAhi/ACFoy57Qn7Es2MjBVCdCqpNXQ00tlDhZVVMetF+d+suuBniycYRSMI3H0bO7Ve4u7UUXPqrBnIPnvq6r9OPLfuiuxsii7sjQHWY1JdKTKnjkGf4BEjCriRlXapti29Js= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744656177; c=relaxed/simple; bh=rbaYOkUTWpyowR7jBDQPIChL648feaPDsQw7fIdQNGE=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=LMYD2rLNuStV0LfgJUmv/PP5uFK308Fz6DOf3r3USvrPiXHeCR2To9BEkDNDEqd1ma6Bnt90Qcuuo8Oge1/+Amp7hYhVf967Uxxd/mKKEP6QcV3xEFr1moeG0NImMFtKoezNNzLC+8Uw7KgScn87Iigg+lCEi1N0U0e5bj+ndvU= 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=WteGvAEy; arc=none smtp.client-ip=209.85.218.42 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="WteGvAEy" Received: by mail-ej1-f42.google.com with SMTP id a640c23a62f3a-ac73228ea73so71563266b.0; Mon, 14 Apr 2025 11:42:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1744656174; x=1745260974; 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=WteGvAEyGO2eoubwQJJpNRTvtOxcBPZUMiSLn0YSSdfrUinn6cL9H7GANFbXtOQLD4 T/E69iYZ/wRlLdEWWHKHaS/c3j1RlmX25Ve7Zzqzn54BloqAXhfb2YLQh3xOIOsjvrDe E3O1FYKTPQKkPRiG+m8xRkQUwRHAXlRC0tmV5SzFoL7SGwDbsShLtelKJRmM0lLnyU63 sb7u/EQ+aLoyU3Geuot7gCVy/H5mnmvhtodXCzvC02+j8l3h1bR9MWCAjogoEOvxu3QS E0gQmvNrrulg3D75lT+Oyn6GHcNcLtBez7cqsZa9G8xAz1reImmU08BI/q/GbQwzr3QI dzrQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1744656174; x=1745260974; 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=gExKmCr8gOR+7s8r2gw95HUJHnDRYWqN4oMTgUBnmbBQ4EVjZ81uh0Yka4UyEX2dQ1 DY7GmxpFLOGxGKngtrqrFMLYpCOQ9AX9zYCs3PgKPxV+iVLgMb/DLpqObVK0+6HVekgC xZcairGg7MDGr/dyrIbaiFZ7Fvpt8DEVseFzMfSY4YZW4Im82KgZMdabnTg/ZFc8iu/i stHYBU084FIWO/5l9boWSRBLED8QP2Ss5P5AK08g/Cj8YqSJfe+KBwSa4ftQQ1cMTqZr 4L9688wNQVnBFaeVsElpUTU9XHX1MjhocN6DEaNeCZ3qiiDuSZGNK+yF43xrgjEjIwm0 95Qw== X-Forwarded-Encrypted: i=1; AJvYcCXAkMcz04QH89B+kvTGI50Tad9bODLTYJoT4CgJknX9nWkVxds/g+iSEt3e3JjhM09q6sxNiNyloMnRWcw=@vger.kernel.org X-Gm-Message-State: AOJu0YwwY72yobu1FJlNX2qNP0JCTf83Mh/dzXTQRiye15GQqMR/CHim w0y9HXDyWDncnRMoZpRbbG0H5RRKjUK9ITXJUKE69xDoBawRUBOE X-Gm-Gg: ASbGncs3g9yTkHdK+tlWmFk8zh5daPKfz1j23BzzsSzfWQJc0LBw5oxKMNBIsNLvjUs pn9MB1uRGU3cvU3mfaVyXPoHM9qeg5hfYu8pmu6mvdWvVoP5q5btPDWkMRFsi832/2RSfZP7CQM 48/aRI9UIl3cgHwRLf3Q2w7DrWppD/xr5FL43qQGRWQJSJs7XJfOT0b0KyiBgQ7dD4AQQVcP/2L OM/MMeVohu/HPA0+p1SbbK80IPJeG/m4jE5IlOY3stVtyo+RFogcnHAZHeNNcwuTsMTot7uXExs naA3sxI+Y85fVnnS9mIfypVT8M8niPgIUuhOuemAYN2KiuPM/BxVsY5CiOFW30qQx8FU8FMID7A eBism8O7AZckQTpkgFs8= X-Google-Smtp-Source: AGHT+IG0MBKskRn2bioPx2eBrmJFIohEDJARFNOI/1LKNC0m9TKnucK0yuRv1maFcU3+ofJgqnFm9w== X-Received: by 2002:a17:907:bc87:b0:ac0:b71e:44e0 with SMTP id a640c23a62f3a-acad34d87admr430536566b.9.1744656173333; Mon, 14 Apr 2025 11:42:53 -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-acaa1bb3172sm946483466b.24.2025.04.14.11.42.52 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 14 Apr 2025 11:42:53 -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 v6 04/11] iio: accel: adxl345: set the tap suppress bit permanently Date: Mon, 14 Apr 2025 18:42:38 +0000 Message-Id: <20250414184245.100280-5-l.rubusch@gmail.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250414184245.100280-1-l.rubusch@gmail.com> References: <20250414184245.100280-1-l.rubusch@gmail.com> Precedence: bulk X-Mailing-List: linux-iio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Set the suppress bit feature to the double tap detection, whenever double tap is enabled. This impedes the suppress bit dangling in any state, and thus varying in sensitivity for double tap detection. Any tap event is defined by a rising signal edge above threshold, i.e. duration time starts counting; and the falling edge under threshold within duration time, i.e. then the tap event is issued. This means duration is used individually for each tap event. For double tap detection after a single tap, a latency time needs to be specified. Usually tap events, i.e. spikes above and returning below threshold will be ignored within latency. After latency, the window time starts counting for a second tap detection which has to happen within a duration time. If the suppress bit is not set, spikes within latency time are ignored. Setting the suppress bit will invalidate the double tap function. The sensor will thus be able to save the window time for double tap detection, and follow a more strict definition of what signal qualifies for a double tap. In a summary having the suppress bit set, fewer signal spikes will be considered as double taps. This is an optional add on to double tap, thus a separate patch. Signed-off-by: Lothar Rubusch --- drivers/iio/accel/adxl345_core.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/iio/accel/adxl345_core.c b/drivers/iio/accel/adxl345_core.c index 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 #define ADXL345_REG_TAP_AXIS_MSK GENMASK(2, 0) +#define ADXL345_REG_TAP_SUPPRESS_MSK BIT(3) +#define ADXL345_REG_TAP_SUPPRESS BIT(3) #define ADXL345_TAP_Z_EN BIT(0) #define ADXL345_TAP_Y_EN BIT(1) @@ -295,6 +297,18 @@ static int adxl345_set_singletap_en(struct adxl345_state *st, static int adxl345_set_doubletap_en(struct adxl345_state *st, bool en) { + int ret; + + /* + * Generally suppress detection of spikes during the latency period as + * double taps here, this is fully optional for double tap detection + */ + ret = regmap_update_bits(st->regmap, ADXL345_REG_TAP_AXIS, + ADXL345_REG_TAP_SUPPRESS_MSK, + en ? ADXL345_REG_TAP_SUPPRESS : 0x00); + if (ret) + return ret; + return _adxl345_set_tap_int(st, ADXL345_DOUBLE_TAP, en); } From patchwork Mon Apr 14 18:42:39 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lothar Rubusch X-Patchwork-Id: 14050879 Received: from mail-ej1-f50.google.com (mail-ej1-f50.google.com [209.85.218.50]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6879028DF12; Mon, 14 Apr 2025 18:42:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.50 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744656178; cv=none; b=PmMS1C3gNHhvW33ZHiaLoK6im1FJt/dE5Yh7fzr7roe8AEmSIsQ4fCZLMmYXNSqTYFOAhP9H1Ih7HTTtLPW7wRa+N7jft9KCj8zAaCPHrUihFqU5ef1rV9+lstxC/Wwi/mCiOVgSLI0blox0WF2ajjVZo7DZCvbC6Tvg++Tuhps= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744656178; c=relaxed/simple; bh=okZLLCEBu0H3RhSIIU1fzQZoC+9KvNdvuWVj0hHY8CQ=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=gAa+iicaKsVXlBOGp6i52E1GjAEDpiCaOqBoMaeip5Xg3g9jUk/Svy9UipLuJQCgBKgk7xWoaPNIh8QUMe12oeK4p4AaBBIGK4japv5XTb4BjMA5WdMsmOs4k/qXuG4xxqeXc06SDWR44A24XtcDr/e37ngyNew6j831aw10mIU= 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=eG83h5zg; arc=none smtp.client-ip=209.85.218.50 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="eG83h5zg" Received: by mail-ej1-f50.google.com with SMTP id a640c23a62f3a-ac2c7a36802so85359166b.2; Mon, 14 Apr 2025 11:42:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1744656174; x=1745260974; 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=xl4fo+5wq9O04rfHJRdTZpJiIbJaDuhNxt56NkmrfbY=; b=eG83h5zgegdyz4a6s3pgJ9xVHdSUgL9n+aLSbgl/dRfEafFuoTnav+Y0ZaFzX/2zoC i+chmhc/R6MEhjsX7WJju6UswYUf1nsB6yRt+hggyxInJ63m1Uethz8fokyEPEl65ZY+ kTzUCpg6ujNqSqKB7n5woWBLPNgAydLyvELnGWcti21xPELLFODCrQ45D+Tvt3KIGnMC jEXmKN+7v2gtDGDohHBAQqJmY2P269+KA9cDRHnxbIizgIZ0JtwmG7S2J/GpOmv6KPuf fDpYxUqEVRDZaH+8kmQ3KAHitoPhPiUUzdSdwUtqPi2PWdrCy4qwYQCM/cOb7En+Y1J6 L1zQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1744656174; x=1745260974; 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=xl4fo+5wq9O04rfHJRdTZpJiIbJaDuhNxt56NkmrfbY=; b=hYZgw37RWETSfNzMHltdpeenqZYm+tEWZXrdfTk2QXv84AahHRUZLNlVtKUwpgqc/h WWr6RyN4OsD69hvn0LX2kGqArR/ZgHvxyjvC0lEzbYZEKowHLIGqbajJgQhNnQcaqMAj dicA9x4N0fnYHWrkz4tzntWSyuDg8vi9GwgFRQEzgn52NNQ8ZYhak0DJ5k+GpUrpzCav iov79WBHUhdg2BqTIx4eoyroO8GOWAFtf46k7l4Ro0tS4DGY+fczlKBkXwRlJjYDyRSb imYH2RUzdXhIRnJVC+Da9bgXYAY2UL5mD+80FN4xx5h/++CduT5B3atLhsFrlw4xR1rg /KZA== X-Forwarded-Encrypted: i=1; AJvYcCW/pbG3Njb2+azqCgR5ZlrXvixG3HkKf/7uBRNMTsNtG0wsz7SXivBq6t3epdk0nyu5P6/Erv6Kv19njYk=@vger.kernel.org X-Gm-Message-State: AOJu0YyG9n/odqiR44pMCHzkUJp+STt9oSzwORGpmHtp2/iIjaPbpYc6 abVlCZ2KFRryq6wDtGCjkFfQmtV6OobNMeg3qkTC2Ae4EZ9+7aM+ X-Gm-Gg: ASbGnctb/xzPwFyRMY/CoOEKcwlSN+aRFhdwrxdLVI4G0c4fy3BnWf5T0OEDX88QY34 +n3vzPIyZIFGQQYZBSzQHVYY+4Bj1gZjZ2+K3n/ZF0r7N1Cp17yc1f94NNvIxiMIF+HKLvv2xgG H5tsZwJ9dC0YoaulsdyOSHHS1ip06iLsC+lJAiKF/Q2Tb5XpXFFJ5sxFBLtIUZI2EEfM1phpDdo GbXV1OUjnrPIoH3pwMFrT5IcJjl8ugKn3VaER37YAN2UYU0haj7uT9i3B/krNM4ERAsKz9JSbJ0 S7t4pkElhWgly0dcPslyARSetvudfdydo2/YSMFeJs5Gw2zYPf7ea1/gQ2wiLvtfXmJA/EAbpME 9cpli5vOoaGL+pATviFo= X-Google-Smtp-Source: AGHT+IERiWRNepLz2BnGPMbtnKAJQ6q+vCT63Sc+FjOnx/eOr5ZLKdeWpHG/ddjekxE9ELxQ94vjbQ== X-Received: by 2002:a17:907:9588:b0:ab7:5fcd:d4db with SMTP id a640c23a62f3a-acad34d88d5mr453359566b.9.1744656174276; Mon, 14 Apr 2025 11:42:54 -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-acaa1bb3172sm946483466b.24.2025.04.14.11.42.53 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 14 Apr 2025 11:42:53 -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 v6 05/11] iio: accel: adxl345: add freefall feature Date: Mon, 14 Apr 2025 18:42:39 +0000 Message-Id: <20250414184245.100280-6-l.rubusch@gmail.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250414184245.100280-1-l.rubusch@gmail.com> References: <20250414184245.100280-1-l.rubusch@gmail.com> Precedence: bulk X-Mailing-List: linux-iio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Add the freefall detection of the sensor together with a threshold and time parameter. A freefall event is detected if the measuring signal falls below the threshold. Introduce a freefall threshold stored in regmap cache, and a freefall time, having the scaled time value stored as a member variable in the state instance. Signed-off-by: Lothar Rubusch --- drivers/iio/accel/adxl345_core.c | 125 +++++++++++++++++++++++++++++++ 1 file changed, 125 insertions(+) diff --git a/drivers/iio/accel/adxl345_core.c b/drivers/iio/accel/adxl345_core.c index c464c87033fb..ae02826e552b 100644 --- a/drivers/iio/accel/adxl345_core.c +++ b/drivers/iio/accel/adxl345_core.c @@ -75,6 +75,7 @@ struct adxl345_state { u32 tap_duration_us; u32 tap_latent_us; u32 tap_window_us; + u32 ff_time_ms; __le16 fifo_buf[ADXL345_DIRS * ADXL345_FIFO_SIZE + 1] __aligned(IIO_DMA_MINALIGN); }; @@ -96,6 +97,14 @@ static struct iio_event_spec adxl345_events[] = { BIT(IIO_EV_INFO_RESET_TIMEOUT) | BIT(IIO_EV_INFO_TAP2_MIN_DELAY), }, + { + /* free fall */ + .type = IIO_EV_TYPE_MAG, + .dir = IIO_EV_DIR_FALLING, + .mask_shared_by_type = BIT(IIO_EV_INFO_ENABLE) | + BIT(IIO_EV_INFO_VALUE) | + BIT(IIO_EV_INFO_PERIOD), + }, }; #define ADXL345_CHANNEL(index, reg, axis) { \ @@ -383,6 +392,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); } +/* freefall */ + +static int adxl345_is_ff_en(struct adxl345_state *st, bool *en) +{ + int ret; + unsigned int regval; + + ret = regmap_read(st->regmap, ADXL345_REG_INT_ENABLE, ®val); + if (ret) + return ret; + + *en = FIELD_GET(ADXL345_INT_FREE_FALL, regval) > 0; + + return 0; +} + +static int adxl345_set_ff_en(struct adxl345_state *st, bool cmd_en) +{ + unsigned int regval, ff_threshold; + bool en; + int ret; + + ret = regmap_read(st->regmap, ADXL345_REG_THRESH_FF, &ff_threshold); + if (ret) + return ret; + + en = cmd_en && ff_threshold > 0 && st->ff_time_ms > 0; + + regval = en ? ADXL345_INT_FREE_FALL : 0x00; + + return regmap_update_bits(st->regmap, ADXL345_REG_INT_ENABLE, + 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 = 1.275000 seconds + * + * Note: the scaling is similar to the scaling in the ADXL380 + */ + if (1000000 * val_int + val_fract_us > 1275000) + return -EINVAL; + + val_ms = val_int * 1000 + DIV_ROUND_UP(val_fract_us, 1000); + st->ff_time_ms = val_ms; + + regval = DIV_ROUND_CLOSEST(val_ms, 5); + + /* Values between 100ms and 350ms (0x14 to 0x46) are recommended. */ + return regmap_write(st->regmap, ADXL345_REG_TIME_FF, min(regval, 0xff)); +} + static int adxl345_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask) @@ -495,6 +561,11 @@ static int adxl345_read_event_config(struct iio_dev *indio_dev, default: return -EINVAL; } + case IIO_EV_TYPE_MAG: + ret = adxl345_is_ff_en(st, &int_en); + if (ret) + return ret; + return int_en; default: return -EINVAL; } @@ -518,6 +589,8 @@ static int adxl345_write_event_config(struct iio_dev *indio_dev, default: return -EINVAL; } + case IIO_EV_TYPE_MAG: + return adxl345_set_ff_en(st, state); default: return -EINVAL; } @@ -532,6 +605,7 @@ static int adxl345_read_event_value(struct iio_dev *indio_dev, { struct adxl345_state *st = iio_priv(indio_dev); unsigned int tap_threshold; + unsigned int ff_threshold; int ret; switch (type) { @@ -565,6 +639,22 @@ static int adxl345_read_event_value(struct iio_dev *indio_dev, default: return -EINVAL; } + case IIO_EV_TYPE_MAG: + switch (info) { + case IIO_EV_INFO_VALUE: + ret = regmap_read(st->regmap, ADXL345_REG_THRESH_FF, + &ff_threshold); + if (ret) + return ret; + *val = ff_threshold; + return IIO_VAL_INT; + case IIO_EV_INFO_PERIOD: + *val = st->ff_time_ms; + *val2 = 1000; + return IIO_VAL_FRACTIONAL; + default: + return -EINVAL; + } default: return -EINVAL; } @@ -612,6 +702,22 @@ static int adxl345_write_event_value(struct iio_dev *indio_dev, return -EINVAL; } break; + case IIO_EV_TYPE_MAG: + switch (info) { + case IIO_EV_INFO_VALUE: + ret = regmap_write(st->regmap, ADXL345_REG_THRESH_FF, val); + if (ret) + return ret; + break; + case IIO_EV_INFO_PERIOD: + ret = adxl345_set_ff_time(st, val, val2); + if (ret) + return ret; + break; + default: + return -EINVAL; + } + break; default: return -EINVAL; } @@ -865,6 +971,17 @@ static int adxl345_push_event(struct iio_dev *indio_dev, int int_stat, return ret; } + if (FIELD_GET(ADXL345_INT_FREE_FALL, int_stat)) { + ret = iio_push_event(indio_dev, + IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, + IIO_MOD_X_OR_Y_OR_Z, + IIO_EV_TYPE_MAG, + IIO_EV_DIR_FALLING), + ts); + if (ret) + return ret; + } + if (FIELD_GET(ADXL345_INT_WATERMARK, int_stat)) { samples = adxl345_get_samples(st); if (samples < 0) @@ -973,6 +1090,7 @@ int adxl345_core_probe(struct device *dev, struct regmap *regmap, ADXL345_DATA_FORMAT_FULL_RES | ADXL345_DATA_FORMAT_SELF_TEST); unsigned int tap_threshold; + unsigned int ff_threshold; int ret; indio_dev = devm_iio_device_alloc(dev, sizeof(*st)); @@ -992,6 +1110,9 @@ int adxl345_core_probe(struct device *dev, struct regmap *regmap, st->tap_window_us = 64; /* 64 [0x40] -> .080 */ st->tap_latent_us = 16; /* 16 [0x10] -> .020 */ + ff_threshold = 8; /* 8 [0x08] */ + st->ff_time_ms = 32; /* 32 [0x20] -> 0.16 */ + indio_dev->name = st->info->name; indio_dev->info = &adxl345_info; indio_dev->modes = INDIO_DIRECT_MODE; @@ -1068,6 +1189,10 @@ int adxl345_core_probe(struct device *dev, struct regmap *regmap, if (ret) return ret; + ret = regmap_write(st->regmap, ADXL345_REG_THRESH_FF, ff_threshold); + if (ret) + return ret; + /* FIFO_STREAM mode is going to be activated later */ ret = devm_iio_kfifo_buffer_setup(dev, indio_dev, &adxl345_buffer_ops); if (ret) From patchwork Mon Apr 14 18:42:40 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lothar Rubusch X-Patchwork-Id: 14050880 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 6D32628E60E; Mon, 14 Apr 2025 18:42:57 +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=1744656179; cv=none; b=SugIIIcliTC3lnxcESWmSalcUDTHeLvnjueE+yMbaAnQWQZketW5nNxWCDKhNjNCmH5Ube0zf5WDY07eteHzRfkBaXiMdiRtHNSjzwa71Ipx51gK3VlrztDSrEBJMFL/B9t+RcTb7P/z/1+2RNQd1RQHogcRkHwowLtXMRCBlEg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744656179; c=relaxed/simple; bh=fHwXgbeTUx55u7qQiE27sU7Pm7D/CJPjxJSy0vTc3GA=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=T5jIvUWOnOYssYx+/LjRC6SSsz0n69ucxg0vRlMdoKwOpO7D3GDIi8L3jkSY/uvgX0Kb1Z0IXk5nAp1RkFiLqZKIdXHaJh4BuUJlj7FhOhDTAGbBCLXvIZaUZSrj1Di/fiF3DPH0Bka2KlDR4OxzjKZVmOrM5Iny/yiksCS48/I= 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=BXNBOfZA; 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="BXNBOfZA" Received: by mail-ej1-f46.google.com with SMTP id a640c23a62f3a-ac8128270f3so86848666b.0; Mon, 14 Apr 2025 11:42:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1744656176; x=1745260976; 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=KBuMDPL8y3kIgNjvfFIK/7ctpt/vRvY4qU5++88fPtI=; b=BXNBOfZArBHj4fIFd9TgiU9gU1KeHkzIif1Ugx9BsPBbOC8HaEYpw/9L4B/HZLGnUb i2sGvnic1UeCj0xddqpl+JinI6aO0Wu5roGyoIlOX6FbXFfIE+uMCCBwil4tEUARJT2q BHgm+dJCVUaSaT0H+wUA4bDBgV8yPm2ro5ssuaLGHY/I9dsQDs4+pJZ1anXK1iUZ+rgs o/Dx3st1cksPrbxtfVfHAMiSG/xNnFWNou0JHsb0vlfDxnDXE8qUrtfu4YJsfsvxBpCo O6fWM+LRGNGZ33/xy5VUC5d+TuW/2E02tA9qt8Tm2r/8w/+BdcsRL/euQjBGLFFD/kub cr3w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1744656176; x=1745260976; 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=KBuMDPL8y3kIgNjvfFIK/7ctpt/vRvY4qU5++88fPtI=; b=w97+TbDxWZeoFU/MQn/R87qLa4SyFErm2vLxBE08BEXO7Xz0bwpaY6WtpuawYKk9Y0 DdpPuSHsNjuGC/C3Ww68CFNZUNIAE6ZNXjG4xOfqNqYNq3AITbZdkFxHelSQLJD5Aegh QdYsak7h5MkpHI8+9DH8Po21+q9ZInqX1Suiy9szhEdgnr/sA8D4Y/rGE0UNRlGeoQ1c e7+E8eqiwycniN/XJqTaHeka2WmacR6vVWVImFtPBDRPXI3DDRJT8nIJxG9QOgFC6Jlo RaP9Fyf2A5+Gp+lzUWVkVBw9rcAAVtQ8NgCe2/M8Xv1clgGgVonOO1u3Wm88bqNIFQSX MJZQ== X-Forwarded-Encrypted: i=1; AJvYcCXavGB67UtYwg3oSkaEqSx1rQd/XhLpMrDHz8OQECYQt9ybODvc5/KltpNPSA3bPWmSj3HWviI/Ab12+oo=@vger.kernel.org X-Gm-Message-State: AOJu0YyIbi1uJHA4xC2WyyJhsTbgx8rylUQQLs9WW4UmD0hWz3lnxIiQ RBMhdREeWYRvYeofYjnaLwgm5v2IRNnLn92QmqxMRAbw0jzicPj0J06jMg== X-Gm-Gg: ASbGncsuEmbALnxqnuH/JPVoGOPZ1pXHC7Ig81BCIw58YpVh8FOZ5cnJQjq7C7gewbB txwmfx7UZlx2c578J0ih7ioZv4HVNCy/VNId+Bb+Ys7/j+gh/TbxWjBWKgFv2U8xRMXRcfBK/wQ 64UudKin3Nhbf79GiDo9dpSJ+VhY6JLr2AT6XE1pEKLMN7x3IQMj4VwKdL+qR4nWcelK67VyoA1 rmw3zUtLK3CmUQGbAxQEdz2asNUemSfaixyEVJXunPnM2zA4maLLydG6bmzd9B1WavBj0yLpQfe CLMB+lCESpCesJAv5UsKJKO8TGyHkHlI4wPFV0lD8nfDS0RUEXp3YMe7e6kOJCNPzgb4Id4X7+H ZP7CldzD9jIyKE42/uXA= X-Google-Smtp-Source: AGHT+IGtG0xb95YaJvCuO28eKltbb7/qiwxfEyQc99Or+Q9jVEPCZylKx2xIUYhisbSP/9vwq2mN8Q== X-Received: by 2002:a17:907:7f8b:b0:aca:fcb3:f0c5 with SMTP id a640c23a62f3a-acb1409c4e6mr16079466b.16.1744656175223; Mon, 14 Apr 2025 11:42:55 -0700 (PDT) Received: from 0e1b0684397b.v.cablecom.net (84-72-156-211.dclient.hispeed.ch. [84.72.156.211]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-acaa1bb3172sm946483466b.24.2025.04.14.11.42.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 14 Apr 2025 11:42:54 -0700 (PDT) From: Lothar Rubusch To: lars@metafoo.de, Michael.Hennerich@analog.com, jic23@kernel.org Cc: linux-iio@vger.kernel.org, linux-kernel@vger.kernel.org, eraretuya@gmail.com, l.rubusch@gmail.com Subject: [PATCH v6 06/11] iio: accel: adxl345: extend sample frequency adjustments Date: Mon, 14 Apr 2025 18:42:40 +0000 Message-Id: <20250414184245.100280-7-l.rubusch@gmail.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250414184245.100280-1-l.rubusch@gmail.com> References: <20250414184245.100280-1-l.rubusch@gmail.com> Precedence: bulk X-Mailing-List: linux-iio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Introduce enums and functions to work with the sample frequency adjustments. Let the sample frequency adjust via IIO and configure a reasonable default. Replace the old static sample frequency handling. During adjustment of bw registers, measuring is disabled and afterwards enabled again. Signed-off-by: Lothar Rubusch --- drivers/iio/accel/adxl345.h | 2 +- drivers/iio/accel/adxl345_core.c | 150 ++++++++++++++++++++++++------- 2 files changed, 118 insertions(+), 34 deletions(-) diff --git a/drivers/iio/accel/adxl345.h b/drivers/iio/accel/adxl345.h index 7d482dd595fa..6c1f96406136 100644 --- a/drivers/iio/accel/adxl345.h +++ b/drivers/iio/accel/adxl345.h @@ -69,7 +69,7 @@ * BW_RATE bits - Bandwidth and output data rate. The default value is * 0x0A, which translates to a 100 Hz output data rate */ -#define ADXL345_BW_RATE GENMASK(3, 0) +#define ADXL345_BW_RATE_MSK GENMASK(3, 0) #define ADXL345_BW_LOW_POWER BIT(4) #define ADXL345_BASE_RATE_NANO_HZ 97656250LL diff --git a/drivers/iio/accel/adxl345_core.c b/drivers/iio/accel/adxl345_core.c index ae02826e552b..3db757edfad3 100644 --- a/drivers/iio/accel/adxl345_core.c +++ b/drivers/iio/accel/adxl345_core.c @@ -64,6 +64,45 @@ static const unsigned int adxl345_tap_time_reg[] = { [ADXL345_TAP_TIME_DUR] = ADXL345_REG_DUR, }; +enum adxl345_odr { + ADXL345_ODR_0P10HZ = 0, + ADXL345_ODR_0P20HZ, + ADXL345_ODR_0P39HZ, + ADXL345_ODR_0P78HZ, + ADXL345_ODR_1P56HZ, + ADXL345_ODR_3P13HZ, + ADXL345_ODR_6P25HZ, + ADXL345_ODR_12P50HZ, + ADXL345_ODR_25HZ, + ADXL345_ODR_50HZ, + ADXL345_ODR_100HZ, + ADXL345_ODR_200HZ, + ADXL345_ODR_400HZ, + ADXL345_ODR_800HZ, + ADXL345_ODR_1600HZ, + ADXL345_ODR_3200HZ, +}; + +/* Certain features recommend 12.5 Hz - 400 Hz ODR */ +static const int adxl345_odr_tbl[][2] = { + [ADXL345_ODR_0P10HZ] = { 0, 97000 }, + [ADXL345_ODR_0P20HZ] = { 0, 195000 }, + [ADXL345_ODR_0P39HZ] = { 0, 390000 }, + [ADXL345_ODR_0P78HZ] = { 0, 781000 }, + [ADXL345_ODR_1P56HZ] = { 1, 562000 }, + [ADXL345_ODR_3P13HZ] = { 3, 125000 }, + [ADXL345_ODR_6P25HZ] = { 6, 250000 }, + [ADXL345_ODR_12P50HZ] = { 12, 500000 }, + [ADXL345_ODR_25HZ] = { 25, 0 }, + [ADXL345_ODR_50HZ] = { 50, 0 }, + [ADXL345_ODR_100HZ] = { 100, 0 }, + [ADXL345_ODR_200HZ] = { 200, 0 }, + [ADXL345_ODR_400HZ] = { 400, 0 }, + [ADXL345_ODR_800HZ] = { 800, 0 }, + [ADXL345_ODR_1600HZ] = { 1600, 0 }, + [ADXL345_ODR_3200HZ] = { 3200, 0 }, +}; + struct adxl345_state { const struct adxl345_chip_info *info; struct regmap *regmap; @@ -116,6 +155,7 @@ static struct iio_event_spec adxl345_events[] = { BIT(IIO_CHAN_INFO_CALIBBIAS), \ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ .scan_index = (index), \ .scan_type = { \ .sign = 's', \ @@ -449,14 +489,53 @@ static int adxl345_set_ff_time(struct adxl345_state *st, u32 val_int, return regmap_write(st->regmap, ADXL345_REG_TIME_FF, min(regval, 0xff)); } +static int adxl345_find_odr(struct adxl345_state *st, int val, + int val2, enum adxl345_odr *odr) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(adxl345_odr_tbl); i++) { + if (val == adxl345_odr_tbl[i][0] && + val2 == adxl345_odr_tbl[i][1]) { + *odr = i; + return 0; + } + } + + return -EINVAL; +} + +static int adxl345_set_odr(struct adxl345_state *st, enum adxl345_odr odr) +{ + return regmap_update_bits(st->regmap, ADXL345_REG_BW_RATE, + ADXL345_BW_RATE_MSK, + FIELD_PREP(ADXL345_BW_RATE_MSK, odr)); +} + +static int adxl345_read_avail(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + const int **vals, int *type, + int *length, long mask) +{ + switch (mask) { + case IIO_CHAN_INFO_SAMP_FREQ: + *vals = (int *)adxl345_odr_tbl; + *type = IIO_VAL_INT_PLUS_MICRO; + *length = ARRAY_SIZE(adxl345_odr_tbl) * 2; + return IIO_AVAIL_LIST; + } + + return -EINVAL; +} + static int adxl345_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask) { struct adxl345_state *st = iio_priv(indio_dev); __le16 accel; - long long samp_freq_nhz; unsigned int regval; + enum adxl345_odr odr; int ret; switch (mask) { @@ -494,12 +573,10 @@ static int adxl345_read_raw(struct iio_dev *indio_dev, ret = regmap_read(st->regmap, ADXL345_REG_BW_RATE, ®val); if (ret) return ret; - - samp_freq_nhz = ADXL345_BASE_RATE_NANO_HZ << - (regval & ADXL345_BW_RATE); - *val = div_s64_rem(samp_freq_nhz, NANOHZ_PER_HZ, val2); - - return IIO_VAL_INT_PLUS_NANO; + odr = FIELD_GET(ADXL345_BW_RATE_MSK, regval); + *val = adxl345_odr_tbl[odr][0]; + *val2 = adxl345_odr_tbl[odr][1]; + return IIO_VAL_INT_PLUS_MICRO; } return -EINVAL; @@ -510,7 +587,12 @@ static int adxl345_write_raw(struct iio_dev *indio_dev, int val, int val2, long mask) { struct adxl345_state *st = iio_priv(indio_dev); - s64 n; + enum adxl345_odr odr; + int ret; + + ret = adxl345_set_measure_en(st, false); + if (ret) + return ret; switch (mask) { case IIO_CHAN_INFO_CALIBBIAS: @@ -518,20 +600,26 @@ static int adxl345_write_raw(struct iio_dev *indio_dev, * 8-bit resolution at +/- 2g, that is 4x accel data scale * factor */ - return regmap_write(st->regmap, - ADXL345_REG_OFS_AXIS(chan->address), - val / 4); + ret = regmap_write(st->regmap, + ADXL345_REG_OFS_AXIS(chan->address), + val / 4); + if (ret) + return ret; + break; case IIO_CHAN_INFO_SAMP_FREQ: - n = div_s64(val * NANOHZ_PER_HZ + val2, - ADXL345_BASE_RATE_NANO_HZ); + ret = adxl345_find_odr(st, val, val2, &odr); + if (ret) + return ret; - return regmap_update_bits(st->regmap, ADXL345_REG_BW_RATE, - ADXL345_BW_RATE, - clamp_val(ilog2(n), 0, - ADXL345_BW_RATE)); + ret = adxl345_set_odr(st, odr); + if (ret) + return ret; + break; + default: + return -EINVAL; } - return -EINVAL; + return adxl345_set_measure_en(st, true); } static int adxl345_read_event_config(struct iio_dev *indio_dev, @@ -760,7 +848,7 @@ static int adxl345_write_raw_get_fmt(struct iio_dev *indio_dev, case IIO_CHAN_INFO_CALIBBIAS: return IIO_VAL_INT; case IIO_CHAN_INFO_SAMP_FREQ: - return IIO_VAL_INT_PLUS_NANO; + return IIO_VAL_INT_PLUS_MICRO; default: return -EINVAL; } @@ -773,19 +861,6 @@ static void adxl345_powerdown(void *ptr) adxl345_set_measure_en(st, false); } -static IIO_CONST_ATTR_SAMP_FREQ_AVAIL( -"0.09765625 0.1953125 0.390625 0.78125 1.5625 3.125 6.25 12.5 25 50 100 200 400 800 1600 3200" -); - -static struct attribute *adxl345_attrs[] = { - &iio_const_attr_sampling_frequency_available.dev_attr.attr, - NULL -}; - -static const struct attribute_group adxl345_attrs_group = { - .attrs = adxl345_attrs, -}; - static int adxl345_set_fifo(struct adxl345_state *st) { unsigned int intio; @@ -1048,9 +1123,9 @@ static irqreturn_t adxl345_irq_handler(int irq, void *p) } static const struct iio_info adxl345_info = { - .attrs = &adxl345_attrs_group, .read_raw = adxl345_read_raw, .write_raw = adxl345_write_raw, + .read_avail = adxl345_read_avail, .write_raw_get_fmt = adxl345_write_raw_get_fmt, .read_event_config = adxl345_read_event_config, .write_event_config = adxl345_write_event_config, @@ -1120,6 +1195,15 @@ int adxl345_core_probe(struct device *dev, struct regmap *regmap, indio_dev->num_channels = ARRAY_SIZE(adxl345_channels); indio_dev->available_scan_masks = adxl345_scan_masks; + /* + * Using I2C at 100kHz would limit the maximum ODR to 200Hz, operation + * at an output rate above the recommended maximum may result in + * undesired behavior. + */ + ret = adxl345_set_odr(st, ADXL345_ODR_200HZ); + if (ret) + return ret; + /* Reset interrupts at start up */ ret = regmap_write(st->regmap, ADXL345_REG_INT_ENABLE, 0x00); if (ret) From patchwork Mon Apr 14 18:42:41 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lothar Rubusch X-Patchwork-Id: 14050881 Received: from mail-ej1-f50.google.com (mail-ej1-f50.google.com [209.85.218.50]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 07F5928E61B; Mon, 14 Apr 2025 18:42:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.50 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744656180; cv=none; b=gJsP1sJqQjEajb95zqeYftt5d3AbIzI5VrmGGr7EOFdHN2SfY7BQE8prjnPzIho9I2k4PxsVrv0JD6FuyifhgtaXeJ1x+y69yDycKETWAFz05DJjiwxZNTMQtnS4pjG8j1jEhcIJrGG5EMbiax2i6br1ZaadqSrnTQXJNPAPVo4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744656180; c=relaxed/simple; bh=p6Zyzr7Iafui86EWzpF6wc+ujlG/FIhDJPDAk7GhMgg=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=clsagYupb+kyHZ+AQyLgXFdzjWoJ+jsVLUvI34MUbeSL2iKvBIb9kL3F9leIqdypcGInXVcyNJLKPZxhyTTnbIzDjojRs/t0jTuPnReRpwnxeEPhSwPf+JHRuPwGZbc97Uy3W5qmg9AFEPvewSFG/hhA4rwyzQMZ8QG9CvaMLTs= 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=DwDioddn; arc=none smtp.client-ip=209.85.218.50 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="DwDioddn" Received: by mail-ej1-f50.google.com with SMTP id a640c23a62f3a-ac3f58b9156so57828166b.1; Mon, 14 Apr 2025 11:42:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1744656176; x=1745260976; 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=UMyvrRvoIga/Ldzp8FDNTbMMeIXb6zc4cLsiCB1GT08=; b=DwDioddntsAMgrC/AMRZ4QELMkuBOZ+Os3DJ/UNhckqigGIIAI2oTFZ5ycptRkLOvv wO0EGjUeRvoeLw+FOQJKS5kjROeDSYPR5O/6k48bX8L2h/zIyeW/nYNJbKw9BPWyLNkE BqkASMGyU5BfCbWeqewnQgOfSUSwgEJk0mHc9bKunxwNApuA0CVlwzg8TjX5fkNvbIQp R1pIUvntCHIFbxWWhQBnPEj4J9kTQs9nN2/+gSn8PkQlNwx97htuRjcPssyAmaTVykjW DnblBlTse2kWQePn77nev/aY022YkGTZT9ZXfbH2qQMTiSzeD7IqL/JzFf4PcvI1D27j Ho3Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1744656176; x=1745260976; 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=UMyvrRvoIga/Ldzp8FDNTbMMeIXb6zc4cLsiCB1GT08=; b=LSRxrRc8h8sxmpAaV+Cs4jMMHPwxsnasIl1DvomZZIW1rgNxhOk5H7etUcO1CpC9a6 C1dpF0MCgj64gLFa1EFah0aBLVqIE5ZIOJh5JMEZgZ86OKLeVP09zQiyKSSCWgZMbA4y HtXqknpyfpWNSensK1+BRKVGx8+QotE7zw0kt4B0SGag7d4DNyRsM2w1p+wbxPDwy0yX 0wHF8jvR89IFGZAqrwIsgKvMXZu2J3CxhWZsFA2imrbNF+o0wU/5kX5tvlj8DfV5y0gE rAuY055lqCi/Su1pLr0xsFHEfn8yUfbi8OfIKLfZfK8IPLxGK1dkfnezbEIE0+KqrmPj 48qQ== X-Forwarded-Encrypted: i=1; AJvYcCV5cmKH5uAyKb0iGgc6Gzrq/VlDEc+a1hVQ7DnMd8nwUO2G/mbsYeC1ucmZU9jW3aFkQk5dCQIjie3eoGg=@vger.kernel.org X-Gm-Message-State: AOJu0Yz2eZ1fU1FpD1elH5izVCGc17bN2ulI8HP4IaXawyB61B2HLMLk caCfnGoKL341pK2YiUIt0z6O7PJn0zw6vUiATi7xprzETMhBGQCHCjrxWg== X-Gm-Gg: ASbGncskAyc2gjLF6ZG0K3s3kr0PC0OqtDm+a1n1u/i+qUE7ogyaBoTJYRjCqZTJkxB b5p02nqip2NxL4UisqRviaPx9FdsAZXm/qLZW6OxPCsatGscqS5B2v7ZizUMtfx/8SV65fsdZLd UrNu0C/nB2oSXxNYeXzGQlVWuQTM6pCmzchfgNnYtnhSgL8pQ3Gps4l1XNm0P0wETKcWGlr+smG wuevdcY/RjHRCk9X1XWGujvt0Hzw7T8x6pKzwj4paIBHb0+JPoEZptDBnJ05GJ+/udZaCsRh+8z Oz0fpgJyl9j812sPpo3dLdTaH2GLYsj8YvOYDRC7neQV7YIybbmvY5FT2Fy2XaUBY4wXYe+EljI v63ztVFNrQ45zcdM8DT8= X-Google-Smtp-Source: AGHT+IFUboRuDSmMZjxOJJqTfWaNVHLBly5dp1XNxo0odnszfJFX+okFrvzVfQdru7gGErM/PH4MvA== X-Received: by 2002:a17:907:c89a:b0:ac3:bd7c:178 with SMTP id a640c23a62f3a-acad35803bfmr409062266b.12.1744656176099; Mon, 14 Apr 2025 11:42: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-acaa1bb3172sm946483466b.24.2025.04.14.11.42.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 14 Apr 2025 11:42: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 v6 07/11] iio: accel: adxl345: add g-range configuration Date: Mon, 14 Apr 2025 18:42:41 +0000 Message-Id: <20250414184245.100280-8-l.rubusch@gmail.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250414184245.100280-1-l.rubusch@gmail.com> References: <20250414184245.100280-1-l.rubusch@gmail.com> Precedence: bulk X-Mailing-List: linux-iio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Introduce a mechanism to be able to configure and work with the available g-ranges keeping the precision of 13 digits. Signed-off-by: Lothar Rubusch --- drivers/iio/accel/adxl345_core.c | 90 ++++++++++++++++++++++++++++++-- 1 file changed, 87 insertions(+), 3 deletions(-) diff --git a/drivers/iio/accel/adxl345_core.c b/drivers/iio/accel/adxl345_core.c index 3db757edfad3..166f549ba375 100644 --- a/drivers/iio/accel/adxl345_core.c +++ b/drivers/iio/accel/adxl345_core.c @@ -83,6 +83,13 @@ enum adxl345_odr { ADXL345_ODR_3200HZ, }; +enum adxl345_range { + ADXL345_2G_RANGE = 0, + ADXL345_4G_RANGE, + ADXL345_8G_RANGE, + ADXL345_16G_RANGE, +}; + /* Certain features recommend 12.5 Hz - 400 Hz ODR */ static const int adxl345_odr_tbl[][2] = { [ADXL345_ODR_0P10HZ] = { 0, 97000 }, @@ -103,6 +110,33 @@ static const int adxl345_odr_tbl[][2] = { [ADXL345_ODR_3200HZ] = { 3200, 0 }, }; +/* + * Full resolution frequency table: + * (g * 2 * 9.80665) / (2^(resolution) - 1) + * + * resolution := 13 (full) + * g := 2|4|8|16 + * + * 2g at 13bit: 0.004789 + * 4g at 13bit: 0.009578 + * 8g at 13bit: 0.019156 + * 16g at 16bit: 0.038312 + */ +static const int adxl345_fullres_range_tbl[][2] = { + [ADXL345_2G_RANGE] = { 0, 4789 }, + [ADXL345_4G_RANGE] = { 0, 9578 }, + [ADXL345_8G_RANGE] = { 0, 19156 }, + [ADXL345_16G_RANGE] = { 0, 38312 }, +}; + +/* scaling */ +static const int adxl345_range_factor_tbl[] = { + [ADXL345_2G_RANGE] = 1, + [ADXL345_4G_RANGE] = 2, + [ADXL345_8G_RANGE] = 4, + [ADXL345_16G_RANGE] = 8, +}; + struct adxl345_state { const struct adxl345_chip_info *info; struct regmap *regmap; @@ -155,7 +189,8 @@ static struct iio_event_spec adxl345_events[] = { BIT(IIO_CHAN_INFO_CALIBBIAS), \ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ BIT(IIO_CHAN_INFO_SAMP_FREQ), \ - .info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_SCALE) | \ + BIT(IIO_CHAN_INFO_SAMP_FREQ), \ .scan_index = (index), \ .scan_type = { \ .sign = 's', \ @@ -512,12 +547,40 @@ static int adxl345_set_odr(struct adxl345_state *st, enum adxl345_odr odr) FIELD_PREP(ADXL345_BW_RATE_MSK, odr)); } +static int adxl345_find_range(struct adxl345_state *st, int val, int val2, + enum adxl345_range *range) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(adxl345_fullres_range_tbl); i++) { + if (val == adxl345_fullres_range_tbl[i][0] && + val2 == adxl345_fullres_range_tbl[i][1]) { + *range = i; + return 0; + } + } + + return -EINVAL; +} + +static int adxl345_set_range(struct adxl345_state *st, enum adxl345_range range) +{ + return regmap_update_bits(st->regmap, ADXL345_REG_DATA_FORMAT, + ADXL345_DATA_FORMAT_RANGE, + FIELD_PREP(ADXL345_DATA_FORMAT_RANGE, range)); +} + static int adxl345_read_avail(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, const int **vals, int *type, int *length, long mask) { switch (mask) { + case IIO_CHAN_INFO_SCALE: + *vals = (int *)adxl345_fullres_range_tbl; + *type = IIO_VAL_INT_PLUS_MICRO; + *length = ARRAY_SIZE(adxl345_fullres_range_tbl) * 2; + return IIO_AVAIL_LIST; case IIO_CHAN_INFO_SAMP_FREQ: *vals = (int *)adxl345_odr_tbl; *type = IIO_VAL_INT_PLUS_MICRO; @@ -536,6 +599,7 @@ static int adxl345_read_raw(struct iio_dev *indio_dev, __le16 accel; unsigned int regval; enum adxl345_odr odr; + enum adxl345_range range; int ret; switch (mask) { @@ -554,8 +618,12 @@ static int adxl345_read_raw(struct iio_dev *indio_dev, *val = sign_extend32(le16_to_cpu(accel), 12); return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: - *val = 0; - *val2 = st->info->uscale; + ret = regmap_read(st->regmap, ADXL345_REG_DATA_FORMAT, ®val); + if (ret) + return ret; + range = FIELD_GET(ADXL345_DATA_FORMAT_RANGE, regval); + *val = adxl345_fullres_range_tbl[range][0]; + *val2 = adxl345_fullres_range_tbl[range][1]; return IIO_VAL_INT_PLUS_MICRO; case IIO_CHAN_INFO_CALIBBIAS: ret = regmap_read(st->regmap, @@ -587,6 +655,7 @@ static int adxl345_write_raw(struct iio_dev *indio_dev, int val, int val2, long mask) { struct adxl345_state *st = iio_priv(indio_dev); + enum adxl345_range range; enum adxl345_odr odr; int ret; @@ -615,6 +684,15 @@ static int adxl345_write_raw(struct iio_dev *indio_dev, if (ret) return ret; break; + case IIO_CHAN_INFO_SCALE: + ret = adxl345_find_range(st, val, val2, &range); + if (ret) + return ret; + + ret = adxl345_set_range(st, range); + if (ret) + return ret; + break; default: return -EINVAL; } @@ -847,6 +925,8 @@ static int adxl345_write_raw_get_fmt(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_CALIBBIAS: return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + return IIO_VAL_INT_PLUS_MICRO; case IIO_CHAN_INFO_SAMP_FREQ: return IIO_VAL_INT_PLUS_MICRO; default: @@ -1204,6 +1284,10 @@ int adxl345_core_probe(struct device *dev, struct regmap *regmap, if (ret) return ret; + ret = adxl345_set_range(st, ADXL345_16G_RANGE); + if (ret) + return ret; + /* Reset interrupts at start up */ ret = regmap_write(st->regmap, ADXL345_REG_INT_ENABLE, 0x00); if (ret) From patchwork Mon Apr 14 18:42:42 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lothar Rubusch X-Patchwork-Id: 14050882 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 166FB28F525; Mon, 14 Apr 2025 18:42:58 +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=1744656181; cv=none; b=bjZra8bpbl8VKcLe65+/UkykAZ1CSs4qlqzEQq38Mds3OkU7pF748FxuMTcMbQcPe+8OOnclYIgVwYm+SgaLmewwYlTNPDYa23BGKJokOKIGmb46XfZU4yN2vLn5qCApMz9npuBhmPDnB2LQXAmcVGycv/D1HTQbj0oYTpDytcQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744656181; c=relaxed/simple; bh=DqMyix5Y2hwLPyspjSRNtK/jRR7d1XA/saXeC/MMJtw=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=ZvFkKCZ42YXewCghC8ItjkMQhQc5nJpgvTRqV0eGD3yg9i6EJpZ1pPEO2T1nbjCkllLP++eGVq15rb6AMAfryGhp0Zan6BOXuFHEUHmgj12Lm9wRqj5jpshFs98fPKUtTLYwQbATk9nifQEN5EFWVO6Cjonaq+j/OQCNRoviAwg= 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=X594cjCl; 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="X594cjCl" Received: by mail-ej1-f44.google.com with SMTP id a640c23a62f3a-ac315695c8fso79646266b.3; Mon, 14 Apr 2025 11:42:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1744656177; x=1745260977; 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=hTMeMv7oT0bknwxdE+4YeT2UNuXEoMAw2r6vfkW7OHc=; b=X594cjClPkHyytQryS54+06Y9RakeBDh+DBcXO7KlUrI0bTYZMVbtxDmUz4EJliUYD dlmMQUhINNHLpx+y0GKjpkGxVrwHftSf2w2gHzC3GcvfmfXMkgcpVoAM0mdOOhIdsU/V rS1CUPF8NnsdH5K7mWtI4oDm3BKYfX0FKfY5vvjeP/ipVJC4iWoS5N9pts0K9PYxI/c4 B940FdH6OOZE4jy3RJstAg3O9gChq65jIRIrsP8BGA5g8bXK3cHBeD1obWPp9DN0BCoW iRW/gyjfDJ2SOtdonQIjvseo+XBq6AB1/xMGx7a4+1aCwDxd8UsXmnEdNR3bW+JmpSlz aSZQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1744656177; x=1745260977; 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=hTMeMv7oT0bknwxdE+4YeT2UNuXEoMAw2r6vfkW7OHc=; b=dIUWuzjdzZVonVUKy+AgM2Pdp9y+PorMlJjmW5RmsELI7AD0bJZQok+4fzvrffu1Ec JUG46i0hRkMBruPLK80GKfjKVGw3myPDDe5rZ/0ZW8A/1Sh/FDxfw8LCHBhaSTauj+ch difQDRz7aDP0CZdMKyQhzAagZqtELrzGLjNg6yokyZYD3u/mLQARdlhsYUKqrHe5YiDQ k8wJNVaJ8neVFZvfw/caV0UGorar1X90LqotY64XrsDYRbAWdGaCV//UqDrnMkXSlTgw 51DgOU2JpEA0lvm2CJAboyoNM1yplVDgrdcDdswY1r669UVWpebAUSFyvKDT9dYFp1Qx +TQQ== X-Forwarded-Encrypted: i=1; AJvYcCVKIjLybevpwXM72Ps2nwxzm9h28FYnp1mkv7nuqYMBpGZxgM5GUK3fnXWeGcmaX48jk0VwuJShkJ1wnZU=@vger.kernel.org X-Gm-Message-State: AOJu0YztWUSe90TvtMSf1+J+SnhqPD2AYmNi8i/Py7a8xAaHOmTZmI/s RtwdQg7eOlUafrluphG0ZYgB8pMrD3JyIh9AIXq3K0eIo30nw5Av5SGk1A== X-Gm-Gg: ASbGnctp72NJ8vVdD8iccMVG4eMUP87r7tjfZTvibo/rG2wilMEGW0Z9LWnQdLj+PkX hSJ7GkoXDmuzmXu8pmjWA+rNkdtmIgjRU48cpGAy/LUfmtqzQXrKrd0TKqQWZEQ1BRuTKL53G7A ynzNfHeIJQsD7z9IOUr2KuNHR7uigcMS+t684sMMhqLzgZnxZYbIa56s23uaj43rA2GS7Vjtg3M UAoG+LpgUhxiR+xWX+EToLnQxtvcUeL8AL0zV/gz9sz0b/NfudXj7r7DeqRna8hnm9V9v1fcyzC hE5DUUw67vdUCCStBL0GXwca0tqrkb+5dT14hYOQAiwSgzNAxaxp0PZ4apHRugOZ8ShRTOWU0gn 09EDHKmzAzOoEbyaFhz0= X-Google-Smtp-Source: AGHT+IG+cKxQSPQ9Pi/Avi5dOTpvsPKIaAV5wzSpxj0yxCGe76mugRilS6h64h/kv6QN0ANa2zMMGg== X-Received: by 2002:a17:907:d804:b0:abf:777e:79f1 with SMTP id a640c23a62f3a-acad3495f6fmr435027966b.5.1744656177002; Mon, 14 Apr 2025 11:42: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-acaa1bb3172sm946483466b.24.2025.04.14.11.42.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 14 Apr 2025 11:42: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 v6 08/11] iio: accel: adxl345: add activity event feature Date: Mon, 14 Apr 2025 18:42:42 +0000 Message-Id: <20250414184245.100280-9-l.rubusch@gmail.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250414184245.100280-1-l.rubusch@gmail.com> References: <20250414184245.100280-1-l.rubusch@gmail.com> Precedence: bulk X-Mailing-List: linux-iio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Make the sensor detect and issue interrupts at activity. Activity events are configured by a threshold stored in regmap cache. Initialize the activity threshold register to a reasonable default value in probe. The value is taken from the older ADXL345 input driver, to provide a similar behavior. Reset the activity/inactivity direction enabling register in probe. Reset and initialization shall bring the sensor in a defined initial state to prevent dangling settings when warm restarting the sensor. Activity, ODR configuration together with the range setting prepare the activity/inactivity hystersesis setup, implemented in a follow up patch. Signed-off-by: Lothar Rubusch --- drivers/iio/accel/adxl345_core.c | 217 ++++++++++++++++++++++++++++++- 1 file changed, 214 insertions(+), 3 deletions(-) diff --git a/drivers/iio/accel/adxl345_core.c b/drivers/iio/accel/adxl345_core.c index 166f549ba375..8f7ea3928cf8 100644 --- a/drivers/iio/accel/adxl345_core.c +++ b/drivers/iio/accel/adxl345_core.c @@ -36,11 +36,16 @@ #define ADXL345_REG_TAP_AXIS_MSK GENMASK(2, 0) #define ADXL345_REG_TAP_SUPPRESS_MSK BIT(3) #define ADXL345_REG_TAP_SUPPRESS BIT(3) +#define ADXL345_REG_ACT_AXIS_MSK GENMASK(6, 4) #define ADXL345_TAP_Z_EN BIT(0) #define ADXL345_TAP_Y_EN BIT(1) #define ADXL345_TAP_X_EN BIT(2) +#define ADXL345_ACT_Z_EN BIT(4) +#define ADXL345_ACT_Y_EN BIT(5) +#define ADXL345_ACT_X_EN BIT(6) + /* single/double tap */ enum adxl345_tap_type { ADXL345_SINGLE_TAP, @@ -64,6 +69,19 @@ static const unsigned int adxl345_tap_time_reg[] = { [ADXL345_TAP_TIME_DUR] = ADXL345_REG_DUR, }; +/* activity/inactivity */ +enum adxl345_activity_type { + ADXL345_ACTIVITY, +}; + +static const unsigned int adxl345_act_int_reg[] = { + [ADXL345_ACTIVITY] = ADXL345_INT_ACTIVITY, +}; + +static const unsigned int adxl345_act_thresh_reg[] = { + [ADXL345_ACTIVITY] = ADXL345_REG_THRESH_ACT, +}; + enum adxl345_odr { ADXL345_ODR_0P10HZ = 0, ADXL345_ODR_0P20HZ, @@ -154,6 +172,13 @@ struct adxl345_state { }; static struct iio_event_spec adxl345_events[] = { + { + /* activity */ + .type = IIO_EV_TYPE_THRESH, + .dir = IIO_EV_DIR_RISING, + .mask_separate = BIT(IIO_EV_INFO_ENABLE), + .mask_shared_by_type = BIT(IIO_EV_INFO_VALUE), + }, { /* single tap */ .type = IIO_EV_TYPE_GESTURE, @@ -256,6 +281,99 @@ static int adxl345_set_measure_en(struct adxl345_state *st, bool en) return regmap_write(st->regmap, ADXL345_REG_POWER_CTL, val); } +/* act/inact */ + +static int adxl345_is_act_inact_en(struct adxl345_state *st, + enum iio_modifier axis, + enum adxl345_activity_type type, bool *en) +{ + unsigned int regval; + u32 axis_ctrl; + int ret; + + ret = regmap_read(st->regmap, ADXL345_REG_ACT_INACT_CTRL, &axis_ctrl); + if (ret) + return ret; + + if (type == ADXL345_ACTIVITY) { + switch (axis) { + case IIO_MOD_X: + *en = FIELD_GET(ADXL345_ACT_X_EN, axis_ctrl); + break; + case IIO_MOD_Y: + *en = FIELD_GET(ADXL345_ACT_Y_EN, axis_ctrl); + break; + case IIO_MOD_Z: + *en = FIELD_GET(ADXL345_ACT_Z_EN, axis_ctrl); + break; + default: + *en = false; + return -EINVAL; + } + } + + if (*en) { + ret = regmap_read(st->regmap, ADXL345_REG_INT_ENABLE, ®val); + if (ret) + return ret; + + *en = 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 = 0; + int ret; + + if (type == ADXL345_ACTIVITY) { + switch (axis) { + case IIO_MOD_X: + axis_ctrl = ADXL345_ACT_X_EN; + break; + case IIO_MOD_Y: + axis_ctrl = ADXL345_ACT_Y_EN; + break; + case IIO_MOD_Z: + axis_ctrl = ADXL345_ACT_Z_EN; + break; + default: + return -EINVAL; + } + } + + if (cmd_en) + ret = regmap_set_bits(st->regmap, + ADXL345_REG_ACT_INACT_CTRL, axis_ctrl); + else + ret = regmap_clear_bits(st->regmap, + ADXL345_REG_ACT_INACT_CTRL, axis_ctrl); + if (ret) + return ret; + + ret = regmap_read(st->regmap, adxl345_act_thresh_reg[type], &threshold); + if (ret) + return ret; + + en = false; + + if (type == ADXL345_ACTIVITY) { + en = 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 */ static int _adxl345_set_tap_int(struct adxl345_state *st, @@ -710,6 +828,18 @@ static int adxl345_read_event_config(struct iio_dev *indio_dev, int ret; switch (type) { + case IIO_EV_TYPE_THRESH: + switch (dir) { + case IIO_EV_DIR_RISING: + ret = adxl345_is_act_inact_en(st, chan->channel2, + ADXL345_ACTIVITY, + &int_en); + if (ret) + return ret; + return int_en; + default: + return -EINVAL; + } case IIO_EV_TYPE_GESTURE: switch (dir) { case IIO_EV_DIR_SINGLETAP: @@ -746,6 +876,14 @@ static int adxl345_write_event_config(struct iio_dev *indio_dev, struct adxl345_state *st = iio_priv(indio_dev); switch (type) { + case IIO_EV_TYPE_THRESH: + switch (dir) { + case IIO_EV_DIR_RISING: + return adxl345_set_act_inact_en(st, chan->channel2, + ADXL345_ACTIVITY, state); + default: + return -EINVAL; + } case IIO_EV_TYPE_GESTURE: switch (dir) { case IIO_EV_DIR_SINGLETAP: @@ -770,11 +908,31 @@ static int adxl345_read_event_value(struct iio_dev *indio_dev, int *val, int *val2) { struct adxl345_state *st = iio_priv(indio_dev); + unsigned int act_threshold; unsigned int tap_threshold; unsigned int ff_threshold; int ret; switch (type) { + case IIO_EV_TYPE_THRESH: + switch (info) { + case IIO_EV_INFO_VALUE: + switch (dir) { + case IIO_EV_DIR_RISING: + ret = regmap_read(st->regmap, + adxl345_act_thresh_reg[ADXL345_ACTIVITY], + &act_threshold); + if (ret) + return ret; + + *val = act_threshold; + return IIO_VAL_INT; + default: + return -EINVAL; + } + default: + return -EINVAL; + } case IIO_EV_TYPE_GESTURE: switch (info) { case IIO_EV_INFO_VALUE: @@ -841,6 +999,25 @@ static int adxl345_write_event_value(struct iio_dev *indio_dev, return ret; switch (type) { + case IIO_EV_TYPE_THRESH: + switch (info) { + case IIO_EV_INFO_VALUE: + switch (dir) { + case IIO_EV_DIR_RISING: + ret = regmap_write(st->regmap, + adxl345_act_thresh_reg[ADXL345_ACTIVITY], + val); + if (ret) + return ret; + break; + default: + return -EINVAL; + } + break; + default: + return -EINVAL; + } + break; case IIO_EV_TYPE_GESTURE: switch (info) { case IIO_EV_INFO_VALUE: @@ -1099,7 +1276,8 @@ static int adxl345_fifo_push(struct iio_dev *indio_dev, } static int adxl345_push_event(struct iio_dev *indio_dev, int int_stat, - enum iio_modifier tap_dir) + enum iio_modifier tap_dir, + enum iio_modifier act_dir) { s64 ts = iio_get_time_ns(indio_dev); struct adxl345_state *st = iio_priv(indio_dev); @@ -1126,6 +1304,16 @@ static int adxl345_push_event(struct iio_dev *indio_dev, int int_stat, return ret; } + if (FIELD_GET(ADXL345_INT_ACTIVITY, int_stat)) { + ret = iio_push_event(indio_dev, + IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, act_dir, + IIO_EV_TYPE_THRESH, + IIO_EV_DIR_RISING), + ts); + if (ret) + return ret; + } + if (FIELD_GET(ADXL345_INT_FREE_FALL, int_stat)) { ret = iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, @@ -1164,6 +1352,7 @@ static irqreturn_t adxl345_irq_handler(int irq, void *p) struct adxl345_state *st = iio_priv(indio_dev); unsigned int regval; enum iio_modifier tap_dir = IIO_NO_MOD; + enum iio_modifier act_dir = IIO_NO_MOD; u32 axis_ctrl; int int_stat; int ret; @@ -1172,7 +1361,8 @@ static irqreturn_t adxl345_irq_handler(int irq, void *p) if (ret) return IRQ_NONE; - if (FIELD_GET(ADXL345_REG_TAP_AXIS_MSK, axis_ctrl)) { + if (FIELD_GET(ADXL345_REG_TAP_AXIS_MSK, axis_ctrl) || + FIELD_GET(ADXL345_REG_ACT_AXIS_MSK, axis_ctrl)) { ret = regmap_read(st->regmap, ADXL345_REG_ACT_TAP_STATUS, ®val); if (ret) return IRQ_NONE; @@ -1183,12 +1373,19 @@ static irqreturn_t adxl345_irq_handler(int irq, void *p) tap_dir = IIO_MOD_Y; else if (FIELD_GET(ADXL345_TAP_X_EN, regval)) tap_dir = IIO_MOD_X; + + if (FIELD_GET(ADXL345_ACT_Z_EN, regval)) + act_dir = IIO_MOD_Z; + else if (FIELD_GET(ADXL345_ACT_Y_EN, regval)) + act_dir = IIO_MOD_Y; + else if (FIELD_GET(ADXL345_ACT_X_EN, regval)) + act_dir = IIO_MOD_X; } if (regmap_read(st->regmap, ADXL345_REG_INT_SOURCE, &int_stat)) return IRQ_NONE; - if (adxl345_push_event(indio_dev, int_stat, tap_dir)) + if (adxl345_push_event(indio_dev, int_stat, tap_dir, act_dir)) goto err; if (FIELD_GET(ADXL345_INT_OVERRUN, int_stat)) @@ -1353,6 +1550,20 @@ int adxl345_core_probe(struct device *dev, struct regmap *regmap, if (ret) return ret; + /* + * 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 = regmap_write(st->regmap, ADXL345_REG_ACT_INACT_CTRL, 0); + if (ret) + return ret; + + ret = regmap_write(st->regmap, ADXL345_REG_THRESH_ACT, 6); + if (ret) + return ret; + ret = regmap_write(st->regmap, ADXL345_REG_THRESH_TAP, tap_threshold); if (ret) return ret; From patchwork Mon Apr 14 18:42:43 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lothar Rubusch X-Patchwork-Id: 14050883 Received: from mail-ej1-f42.google.com (mail-ej1-f42.google.com [209.85.218.42]) (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 0974228F53F; Mon, 14 Apr 2025 18:42:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.42 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744656182; cv=none; b=XO4Ne+aAEvEIdspBBK6vog1RTFIGmEyaiuWbxZvrYWD7DkKPk3blQfnMEy1jKgS9mMjQnhETUQupJO3eR3QZJHENQTeblkJLcuwyZYoHLI/1cLZgSAvAS1N84diQEsWc5YI99VqUuqJdbP7uH+K5tcEeUKljUPyjzd7SE1nXaac= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744656182; c=relaxed/simple; bh=YOMlR7TdCyBNlhGj7tRjjFT+MWcgByluqM+7PRgGt/k=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=nniAYPOeaEL+MdicZ/WrNdYpZu+kLKrp4e1jok27VWeJOeYwcu4ACfJhYoaX27SFgAHv49+J597GGsbxwocXCH3lt1wk6GAy393ooAC/YrSwpjiPgF3me0gU5IZ3wMHjM9d7U8PHiq+8mSHINN5QpPIg6eNcomi0yBcGFOto7Qc= 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=HextjZeN; arc=none smtp.client-ip=209.85.218.42 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="HextjZeN" Received: by mail-ej1-f42.google.com with SMTP id a640c23a62f3a-ac3beea7762so82843366b.2; Mon, 14 Apr 2025 11:42:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1744656178; x=1745260978; 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=pdFDpOvEMqCrv1jBxgIkIT+BVlSneRjafPjX/IRKJQc=; b=HextjZeNB6SWGvzZuCB7P+h4I5wuRdj2wyQVk/zF23x/AvlDcnIhgURogDlTTU1Tf0 iZkPwLFZ9T00L0Mxsbs6uXk61AQOlZ9OHVcEMa3lIIBoA3GtuG+JBDnoogstuz84/3Hc 9VvaYWbdBVjdZMUUy58E1U61XDJ43JWuG3KFjRl4OHhnnXxzWq0gSBNaMKp80I/Gm2KM uJsu2NN77mG4KtoeavYVcgRxEvjKjTkFhCh1J2b8FW1FJs5DVqhix7TUG3ag0E2LUddB AE9PM+X4WaNF1OaSAA9l+YUD6f3RFR6fbpNvY62qpIsewIQ7+H5T9M9Kqa5JP2GI5BLV jJHA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1744656178; x=1745260978; 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=pdFDpOvEMqCrv1jBxgIkIT+BVlSneRjafPjX/IRKJQc=; b=cjb+Fvu2EatXrtT6NGlrOSWqwQ0QoFx0pWH4ISTnCo1mkhHtLuACDGSXoHrybw4YWV PrdzlcH0/Ti5TGmvRHr2ykyoIRUbqefk0qLKi4shghK5Y1KC2GVTlGm2IuPuvk0L75ic jPuUvX0fxWNirYv4wDbYnA0gKKG2LHpPjLQ0yPum28eO/TQ6cwL40jca/EUPyCgXieQb i01PHYWeL8rHwXdFYsjNJPfJoS99tgS8jWZZhwMUQwTooIO/a+AxYyL87SSZowpa6A4/ aHijcNZrcRJ5DQ28XQl1LcBEDHpx0pzmwmCJogkCrmjhj3HUBUiJ1fMkmsFYFQp9vQAo 30SQ== X-Forwarded-Encrypted: i=1; AJvYcCUwdjDpyY0M/Ozf0l6EN1HMLucip1FnCiPdtDImyYZ9kXKvn0sazFs56TKgEIlWDiBbfUdj7aH07InGWoA=@vger.kernel.org X-Gm-Message-State: AOJu0YwrsJ8yXvo4TyBUNkuVMBSyGAh4yeuR2yvr5ysL5X7XnxlmP0Fm +pMjubCsSCtaMMtNjtbEmCm78OSGn+Oyd8E1yvPteSWu83M/HT5d X-Gm-Gg: ASbGncu1leNhM2FtTHObzFXuOl7sIDfq+ohUv/qdl0gHvku/nv6YBiLGF2wpKHMN1o1 JCU3eeZwuHuCktXHtVJLvr3m55D79IpnDuSjlo1GnMWT8F9pS8lCI/b7uNR8OrTE/0slsT/D9k7 tpnhQVsroe7xrEtSK/387cS//yQAqY4DZAOmNolDQlU8pWVw8kbR5RMB/XInZTwbYhhxJQ+RBsJ xiS/K3SMIpDaMeGq//ccVCkaE++f5zgPMHwGFUfpqyuGtmIu/XtPIxfg8YJSCgCLC8l3ozkEnM+ zhSkLoZFVbuhuakg+HmuKxyB/QYShr/itQ+Z7aFBVYfpj/JN7EnP0yC91ZssdDInrCc60etLGNR vZCqCD7bpYxyM/HR3QT8= X-Google-Smtp-Source: AGHT+IHyRjmAnf8m11PxyvJevvgCOrZKVW+VjblABI98nub3tQK1gsn00VNEMiVOLp5pTCCMjVEbzA== X-Received: by 2002:a17:907:c8a8:b0:aca:bd09:3cf2 with SMTP id a640c23a62f3a-acad36a1dc6mr394448966b.13.1744656177993; Mon, 14 Apr 2025 11:42: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-acaa1bb3172sm946483466b.24.2025.04.14.11.42.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 14 Apr 2025 11:42: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 v6 09/11] iio: accel: adxl345: add inactivity feature Date: Mon, 14 Apr 2025 18:42:43 +0000 Message-Id: <20250414184245.100280-10-l.rubusch@gmail.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250414184245.100280-1-l.rubusch@gmail.com> References: <20250414184245.100280-1-l.rubusch@gmail.com> Precedence: bulk X-Mailing-List: linux-iio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Add the inactivity feature of the sensor. When activity and inactivity are enabled, a link bit will be set linking activity and inactivity handling. Additionally, the auto-sleep mode will be enabled. Due to the link bit the sensor is going to auto-sleep when inactivity was detected. Inactivity detection needs a threshold to be configured, and a time after which it will go into inactivity state if measurements under threshold. When a ODR is configured this time for inactivity is adjusted with a corresponding reasonable default value, in order to have higher frequencies and lower inactivity times, and lower sample frequency but give more time until inactivity. Both with reasonable upper and lower boundaries, since many of the sensor's features (e.g. auto-sleep) will need to operate beween 12.5 Hz and 400 Hz. This is a default setting when actively changing sample frequency, explicitly setting the time until inactivity will overwrite the default. Similarly, setting the g-range will provide a default value for the activity and inactivity thresholds. Both are implicit defaults, but equally can be overwritten to be explicitly configured. Signed-off-by: Lothar Rubusch --- drivers/iio/accel/adxl345_core.c | 173 ++++++++++++++++++++++++++++++- 1 file changed, 168 insertions(+), 5 deletions(-) diff --git a/drivers/iio/accel/adxl345_core.c b/drivers/iio/accel/adxl345_core.c index 8f7ea3928cf8..06028eaef9e0 100644 --- a/drivers/iio/accel/adxl345_core.c +++ b/drivers/iio/accel/adxl345_core.c @@ -37,11 +37,17 @@ #define ADXL345_REG_TAP_SUPPRESS_MSK BIT(3) #define ADXL345_REG_TAP_SUPPRESS BIT(3) #define ADXL345_REG_ACT_AXIS_MSK GENMASK(6, 4) +#define ADXL345_REG_INACT_AXIS_MSK GENMASK(2, 0) +#define ADXL345_POWER_CTL_INACT_MSK (ADXL345_POWER_CTL_AUTO_SLEEP | ADXL345_POWER_CTL_LINK) #define ADXL345_TAP_Z_EN BIT(0) #define ADXL345_TAP_Y_EN BIT(1) #define ADXL345_TAP_X_EN BIT(2) +#define ADXL345_INACT_Z_EN BIT(0) +#define ADXL345_INACT_Y_EN BIT(1) +#define ADXL345_INACT_X_EN BIT(2) + #define ADXL345_ACT_Z_EN BIT(4) #define ADXL345_ACT_Y_EN BIT(5) #define ADXL345_ACT_X_EN BIT(6) @@ -72,14 +78,17 @@ static const unsigned int adxl345_tap_time_reg[] = { /* activity/inactivity */ enum adxl345_activity_type { ADXL345_ACTIVITY, + ADXL345_INACTIVITY, }; static const unsigned int adxl345_act_int_reg[] = { [ADXL345_ACTIVITY] = ADXL345_INT_ACTIVITY, + [ADXL345_INACTIVITY] = ADXL345_INT_INACTIVITY, }; static const unsigned int adxl345_act_thresh_reg[] = { [ADXL345_ACTIVITY] = ADXL345_REG_THRESH_ACT, + [ADXL345_INACTIVITY] = ADXL345_REG_THRESH_INACT, }; enum adxl345_odr { @@ -179,6 +188,14 @@ static struct iio_event_spec adxl345_events[] = { .mask_separate = BIT(IIO_EV_INFO_ENABLE), .mask_shared_by_type = BIT(IIO_EV_INFO_VALUE), }, + { + /* inactivity */ + .type = IIO_EV_TYPE_THRESH, + .dir = IIO_EV_DIR_FALLING, + .mask_separate = BIT(IIO_EV_INFO_ENABLE), + .mask_shared_by_type = BIT(IIO_EV_INFO_VALUE) | + BIT(IIO_EV_INFO_PERIOD), + }, { /* single tap */ .type = IIO_EV_TYPE_GESTURE, @@ -278,7 +295,8 @@ static int adxl345_set_measure_en(struct adxl345_state *st, bool en) { unsigned int val = en ? ADXL345_POWER_CTL_MEASURE : ADXL345_POWER_CTL_STANDBY; - 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); } /* act/inact */ @@ -310,6 +328,21 @@ static int adxl345_is_act_inact_en(struct adxl345_state *st, *en = false; return -EINVAL; } + } else { + switch (axis) { + case IIO_MOD_X: + *en = FIELD_GET(ADXL345_INACT_X_EN, axis_ctrl); + break; + case IIO_MOD_Y: + *en = FIELD_GET(ADXL345_INACT_Y_EN, axis_ctrl); + break; + case IIO_MOD_Z: + *en = FIELD_GET(ADXL345_INACT_Z_EN, axis_ctrl); + break; + default: + *en = false; + return -EINVAL; + } } if (*en) { @@ -329,6 +362,7 @@ static int adxl345_set_act_inact_en(struct adxl345_state *st, bool cmd_en) { bool en; + unsigned int inact_time_s; unsigned int threshold; u32 axis_ctrl = 0; int ret; @@ -347,6 +381,20 @@ static int adxl345_set_act_inact_en(struct adxl345_state *st, default: return -EINVAL; } + } else { + switch (axis) { + case IIO_MOD_X: + axis_ctrl = ADXL345_INACT_X_EN; + break; + case IIO_MOD_Y: + axis_ctrl = ADXL345_INACT_Y_EN; + break; + case IIO_MOD_Z: + axis_ctrl = ADXL345_INACT_Z_EN; + break; + default: + return -EINVAL; + } } if (cmd_en) @@ -367,11 +415,69 @@ static int adxl345_set_act_inact_en(struct adxl345_state *st, if (type == ADXL345_ACTIVITY) { en = FIELD_GET(ADXL345_REG_ACT_AXIS_MSK, axis_ctrl) && threshold; + } else { + ret = regmap_read(st->regmap, ADXL345_REG_TIME_INACT, &inact_time_s); + if (ret) + return ret; + + en = FIELD_GET(ADXL345_REG_INACT_AXIS_MSK, axis_ctrl) && + threshold && inact_time_s; } - return regmap_update_bits(st->regmap, ADXL345_REG_INT_ENABLE, - adxl345_act_int_reg[type], - en ? adxl345_act_int_reg[type] : 0); + ret = regmap_update_bits(st->regmap, ADXL345_REG_INT_ENABLE, + adxl345_act_int_reg[type], + en ? adxl345_act_int_reg[type] : 0); + if (ret) + return ret; + + return regmap_update_bits(st->regmap, ADXL345_REG_POWER_CTL, + ADXL345_POWER_CTL_INACT_MSK, + en ? (ADXL345_POWER_CTL_AUTO_SLEEP | ADXL345_POWER_CTL_LINK) + : 0); +} + +/** + * adxl345_set_inact_time_s - Configure inactivity time explicitly or by ODR. + * @st: The sensor state instance. + * @val_s: A desired time value, between 0 and 255. + * + * 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 computed. + * + * In such case, it should take power consumption into consideration. Thus it + * shall be shorter for higher frequencies and longer for lower frequencies. + * Hence, frequencies above 255 Hz shall default to 10 s and frequencies below + * 10 Hz shall result in 255 s to detect inactivity. + * + * The approach simply subtracts the pre-decimal figure of the configured + * sample frequency from 255 s to compute inactivity time [s]. Sub-Hz are thus + * ignored in this estimation. The recommended ODRs for various features + * (activity/inactivity, sleep modes, free fall, etc.) lie between 12.5 Hz and + * 400 Hz, thus higher or lower frequencies will result in the boundary + * defaults or need to be explicitly specified via val_s. + * + * Return: 0 or error value. + */ +static int adxl345_set_inact_time_s(struct adxl345_state *st, u32 val_s) +{ + unsigned int max_boundary = 255; + unsigned int min_boundary = 10; + unsigned int val = min(val_s, max_boundary); + enum adxl345_odr odr; + unsigned int regval; + int ret; + + if (val == 0) { + ret = regmap_read(st->regmap, ADXL345_REG_BW_RATE, ®val); + if (ret) + return ret; + odr = FIELD_GET(ADXL345_BW_RATE_MSK, regval); + + val = (adxl345_odr_tbl[odr][0] > max_boundary) + ? min_boundary : max_boundary - adxl345_odr_tbl[odr][0]; + } + + return regmap_write(st->regmap, ADXL345_REG_TIME_INACT, val); } /* tap */ @@ -837,6 +943,13 @@ static int adxl345_read_event_config(struct iio_dev *indio_dev, if (ret) return ret; return int_en; + case IIO_EV_DIR_FALLING: + ret = adxl345_is_act_inact_en(st, chan->channel2, + ADXL345_INACTIVITY, + &int_en); + if (ret) + return ret; + return int_en; default: return -EINVAL; } @@ -881,6 +994,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; } @@ -908,7 +1024,8 @@ static int adxl345_read_event_value(struct iio_dev *indio_dev, int *val, int *val2) { struct adxl345_state *st = iio_priv(indio_dev); - unsigned int act_threshold; + unsigned int act_threshold, inact_threshold; + unsigned int inact_time_s; unsigned int tap_threshold; unsigned int ff_threshold; int ret; @@ -927,9 +1044,24 @@ static int adxl345_read_event_value(struct iio_dev *indio_dev, *val = act_threshold; return IIO_VAL_INT; + case IIO_EV_DIR_FALLING: + ret = regmap_read(st->regmap, + adxl345_act_thresh_reg[ADXL345_INACTIVITY], + &inact_threshold); + if (ret) + return ret; + + *val = inact_threshold; + return IIO_VAL_INT; default: return -EINVAL; } + case IIO_EV_INFO_PERIOD: + ret = regmap_read(st->regmap, ADXL345_REG_TIME_INACT, &inact_time_s); + if (ret) + return ret; + *val = inact_time_s; + return IIO_VAL_INT; default: return -EINVAL; } @@ -1010,10 +1142,22 @@ static int adxl345_write_event_value(struct iio_dev *indio_dev, if (ret) return ret; break; + case IIO_EV_DIR_FALLING: + ret = regmap_write(st->regmap, + adxl345_act_thresh_reg[ADXL345_INACTIVITY], + val); + if (ret) + return ret; + break; default: return -EINVAL; } break; + case IIO_EV_INFO_PERIOD: + ret = adxl345_set_inact_time_s(st, val); + if (ret) + return ret; + break; default: return -EINVAL; } @@ -1314,6 +1458,17 @@ static int adxl345_push_event(struct iio_dev *indio_dev, int int_stat, return ret; } + if (FIELD_GET(ADXL345_INT_INACTIVITY, int_stat)) { + ret = iio_push_event(indio_dev, + IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, + IIO_MOD_X_OR_Y_OR_Z, + IIO_EV_TYPE_THRESH, + IIO_EV_DIR_FALLING), + ts); + if (ret) + return ret; + } + if (FIELD_GET(ADXL345_INT_FREE_FALL, int_stat)) { ret = iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, @@ -1560,10 +1715,18 @@ int adxl345_core_probe(struct device *dev, struct regmap *regmap, if (ret) return ret; + ret = regmap_write(st->regmap, ADXL345_REG_TIME_INACT, 3); + if (ret) + return ret; + ret = regmap_write(st->regmap, ADXL345_REG_THRESH_ACT, 6); if (ret) return ret; + ret = regmap_write(st->regmap, ADXL345_REG_THRESH_INACT, 4); + if (ret) + return ret; + ret = regmap_write(st->regmap, ADXL345_REG_THRESH_TAP, tap_threshold); if (ret) return ret; From patchwork Mon Apr 14 18:42:44 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lothar Rubusch X-Patchwork-Id: 14050884 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 3733E291168; Mon, 14 Apr 2025 18:43:01 +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=1744656183; cv=none; b=V+9pMpzVOOmWc5rY120re/OA8HQjslElqp62VZp6uknWouTMKlKmQCzn/uuCiUaKHalyRC+t78I4DYHGNlCsxxBdMQXORPMkqNYg2TtDm6KZ0UiI3LKvwyTxTE0WLGkESUPn5dIc9M5ze1+y13RoGqyMAAgs3w5q2EpMl9fFkGA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744656183; c=relaxed/simple; bh=wyyagOiACiCvVPtfTegoqZcSdk91zKhMmUH1jo4csWA=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=bullYokX2UtCViSpa083jY8K98GWUQFKXh+Z9DgLCi8Eo5XJtlpDQKElKKyMV7gIJt/oa2W6maRhw0i3Jwwb38e05z/2gVIbEOPTPx7gRmR5HiQ1eSEFxl9ajxG+Kf0Jc0iCVz5BuSbvMmUMyJcP2jVl0XGxhg7eztNSnCndRhM= 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=ecFwJW/S; 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="ecFwJW/S" Received: by mail-ej1-f46.google.com with SMTP id a640c23a62f3a-acb03ad9213so21486766b.1; Mon, 14 Apr 2025 11:43:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1744656179; x=1745260979; 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=8lGIF7lExxCuuWmnKyS0UqvwvU1UEvZCkmq6EdHYGAg=; b=ecFwJW/SROTX2xMl4xRl0OgRh0iZ4z0xDtBPhi4tkBIpTeTvwW3T5cmd9FUceeDa0m EAI6U/aGzOoQyJDmVCePYQrTQsNAjYRpPxObLxFNALdu9i3viwgGmZiWydtrgOBqnuIG VY6zvzhqDwwnjM41QrJ10A1+GqgJTh0CGOxHJ1yqPbl+S/YjqheWn8hNW3ucGbkpNJcW /bMoTLUOz5q0U9lzJ0fpKDq0Veb/o4rj+2eL/slnL0PEA1ZSL9ENnF2kB3pLg2qVcoOL Kcyu2zEtYiumi4Cwupz6yFkyjsyaO7XviTju4BGqhTEl/PIkKXRe+2gQ+IF05h5LA7/Z n0mQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1744656179; x=1745260979; 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=8lGIF7lExxCuuWmnKyS0UqvwvU1UEvZCkmq6EdHYGAg=; b=SYklnQVaY1ih4mFJC69Yt5Xf3F+Kn0prixbgEKCeHXJmsxatf7tWEHASoA/sQqKP/d LeWT5n+dnNrbdjEakCgoac5mcnAfmDLxGkWg3qSSY2M6X3gp83307Nl3YNF++bTP5N2N 4iR138KBgNAIucAp0m5P2GhcFQAmtH2n+ItsL1jkVGdX/37CrfSlLwBnbILQxH2WFtiG MlZQPDHS2aoWTF1OSOh6gLMRMRpXhw3cPDP29tlGOldyU5jT0cX8ikxvLUKX6Wwdsezw gkK8B5HZQcTau3ZxbQFu4IZAE1pXlmBW09YNsfYLFqR1s2x3eHBYxNbCDo/RXHSkQLjg 2sYA== X-Forwarded-Encrypted: i=1; AJvYcCXF/5gFCzCecF/zqHjTmN9NGUYF/2+Mc7Z9W3eK28C8KX5hjuO3bv/TkhPomiSLkByU/HvJYhSe3dcp/BU=@vger.kernel.org X-Gm-Message-State: AOJu0Yz4JcHuRB9uqmJ+mT1tAP5hJPuS2l/kFdSPIWVkoQ9m2aZsVIIQ 0lkrMug+6JGyie5BZnV35oZVDGkyKNRjth7sXz6csxrd7UrbQGb2 X-Gm-Gg: ASbGncs0P2l5mvLHT27zBrM20wzG9wwRUPIjLZAZ7AP3Pe5FFMgqEDbanH/wyhuisyV pG8EBsrRzxKXvkQvu5x0ENPMfKneO68ZUYSfSLLWfqAGhXY/ECQ/3hMWF7T0ichQd3WZrfsPCoX FyPIxLYPWg9ggP1i+GGhu+QF2kfLcHNUafWQDL2ApHt2TTMBIJTRvNxfjD26rBzt8GgjHqzckmU hcMZBI4Oy7DO86GC2GRgp6lN5+jBPygPPCKQbxNaaDeR8iT4Oo5xXPUvxOzeleipcjFRGtPdds1 oYCa3BKWCNle1VUgmU1mz8t50WKzsWQAWFGgCDKJj5cLthbKMvuz5W5fCXzxQ3oJiIHXqg71tDf E1PPF1dz/I3Qf2fWLKqU= X-Google-Smtp-Source: AGHT+IHF4DrARXQVjjak5Z1Wdy3qdUxQveOk6nBfOOVKDEbbEdo1Wslk14hCzE62dTyT2+LJ+lOv3w== X-Received: by 2002:a17:907:9593:b0:ac7:9237:60a8 with SMTP id a640c23a62f3a-acb13da62fdmr24073366b.9.1744656179027; Mon, 14 Apr 2025 11:42: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-acaa1bb3172sm946483466b.24.2025.04.14.11.42.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 14 Apr 2025 11:42: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 v6 10/11] iio: accel: adxl345: add coupling detection for activity/inactivity Date: Mon, 14 Apr 2025 18:42:44 +0000 Message-Id: <20250414184245.100280-11-l.rubusch@gmail.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250414184245.100280-1-l.rubusch@gmail.com> References: <20250414184245.100280-1-l.rubusch@gmail.com> Precedence: bulk X-Mailing-List: linux-iio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Add coupling activity/inactivity detection by the AC/DC bit. This is an addititional enhancement for the detection of activity states and completes the activity / inactivity feature of the ADXL345. Signed-off-by: Lothar Rubusch --- drivers/iio/accel/adxl345_core.c | 162 ++++++++++++++++++++++++++++++- 1 file changed, 159 insertions(+), 3 deletions(-) diff --git a/drivers/iio/accel/adxl345_core.c b/drivers/iio/accel/adxl345_core.c index 06028eaef9e0..fe0201c7bec6 100644 --- a/drivers/iio/accel/adxl345_core.c +++ b/drivers/iio/accel/adxl345_core.c @@ -37,7 +37,9 @@ #define ADXL345_REG_TAP_SUPPRESS_MSK BIT(3) #define ADXL345_REG_TAP_SUPPRESS BIT(3) #define ADXL345_REG_ACT_AXIS_MSK GENMASK(6, 4) +#define ADXL345_REG_ACT_ACDC_MSK BIT(7) #define ADXL345_REG_INACT_AXIS_MSK GENMASK(2, 0) +#define ADXL345_REG_INACT_ACDC_MSK BIT(3) #define ADXL345_POWER_CTL_INACT_MSK (ADXL345_POWER_CTL_AUTO_SLEEP | ADXL345_POWER_CTL_LINK) #define ADXL345_TAP_Z_EN BIT(0) @@ -91,6 +93,11 @@ static const unsigned int adxl345_act_thresh_reg[] = { [ADXL345_INACTIVITY] = ADXL345_REG_THRESH_INACT, }; +static const unsigned int adxl345_act_acdc_msk[] = { + [ADXL345_ACTIVITY] = ADXL345_REG_ACT_ACDC_MSK, + [ADXL345_INACTIVITY] = ADXL345_REG_INACT_ACDC_MSK, +}; + enum adxl345_odr { ADXL345_ODR_0P10HZ = 0, ADXL345_ODR_0P20HZ, @@ -220,6 +227,18 @@ static struct iio_event_spec adxl345_events[] = { BIT(IIO_EV_INFO_VALUE) | BIT(IIO_EV_INFO_PERIOD), }, + { + /* activity, activity - ac bit */ + .type = IIO_EV_TYPE_MAG_REFERENCED, + .dir = IIO_EV_DIR_RISING, + .mask_shared_by_type = BIT(IIO_EV_INFO_ENABLE), + }, + { + /* activity, inactivity - ac bit */ + .type = IIO_EV_TYPE_MAG_REFERENCED, + .dir = IIO_EV_DIR_FALLING, + .mask_shared_by_type = BIT(IIO_EV_INFO_ENABLE), + }, }; #define ADXL345_CHANNEL(index, reg, axis) { \ @@ -301,6 +320,69 @@ static int adxl345_set_measure_en(struct adxl345_state *st, bool en) /* act/inact */ +static int adxl345_is_act_inact_ac(struct adxl345_state *st, + enum adxl345_activity_type type, bool *ac) +{ + unsigned int regval; + int ret; + + ret = regmap_read(st->regmap, ADXL345_REG_ACT_INACT_CTRL, ®val); + if (ret) + return ret; + + if (type == ADXL345_ACTIVITY) + *ac = FIELD_GET(ADXL345_REG_ACT_ACDC_MSK, regval); + else + *ac = 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 = 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) @@ -766,9 +848,16 @@ static int adxl345_find_odr(struct adxl345_state *st, int val, static int adxl345_set_odr(struct adxl345_state *st, enum adxl345_odr odr) { - return regmap_update_bits(st->regmap, ADXL345_REG_BW_RATE, + int ret; + + ret = regmap_update_bits(st->regmap, ADXL345_REG_BW_RATE, ADXL345_BW_RATE_MSK, FIELD_PREP(ADXL345_BW_RATE_MSK, odr)); + if (ret) + return ret; + + /* update inactivity time by ODR */ + return adxl345_set_inact_time_s(st, 0); } static int adxl345_find_range(struct adxl345_state *st, int val, int val2, @@ -789,9 +878,51 @@ static int adxl345_find_range(struct adxl345_state *st, int val, int val2, static int adxl345_set_range(struct adxl345_state *st, enum adxl345_range range) { - return regmap_update_bits(st->regmap, ADXL345_REG_DATA_FORMAT, + unsigned int act_threshold, inact_threshold; + unsigned int range_old; + unsigned int regval; + int ret; + + ret = regmap_read(st->regmap, ADXL345_REG_DATA_FORMAT, ®val); + if (ret) + return ret; + range_old = FIELD_GET(ADXL345_DATA_FORMAT_RANGE, regval); + + ret = regmap_read(st->regmap, + adxl345_act_thresh_reg[ADXL345_ACTIVITY], + &act_threshold); + if (ret) + return ret; + + ret = regmap_read(st->regmap, + adxl345_act_thresh_reg[ADXL345_INACTIVITY], + &inact_threshold); + if (ret) + return ret; + + ret = regmap_update_bits(st->regmap, ADXL345_REG_DATA_FORMAT, ADXL345_DATA_FORMAT_RANGE, FIELD_PREP(ADXL345_DATA_FORMAT_RANGE, range)); + if (ret) + return ret; + + act_threshold = act_threshold + * adxl345_range_factor_tbl[range_old] + / adxl345_range_factor_tbl[range]; + act_threshold = min(255, max(1, inact_threshold)); + + inact_threshold = inact_threshold + * adxl345_range_factor_tbl[range_old] + / adxl345_range_factor_tbl[range]; + inact_threshold = min(255, max(1, inact_threshold)); + + ret = regmap_write(st->regmap, adxl345_act_thresh_reg[ADXL345_ACTIVITY], + act_threshold); + if (ret) + return ret; + + return regmap_write(st->regmap, adxl345_act_thresh_reg[ADXL345_INACTIVITY], + inact_threshold); } static int adxl345_read_avail(struct iio_dev *indio_dev, @@ -930,7 +1061,7 @@ static int adxl345_read_event_config(struct iio_dev *indio_dev, enum iio_event_direction dir) { struct adxl345_state *st = iio_priv(indio_dev); - bool int_en; + bool int_en, act_ac, inact_ac; int ret; switch (type) { @@ -975,6 +1106,21 @@ static int adxl345_read_event_config(struct iio_dev *indio_dev, if (ret) return ret; return int_en; + case IIO_EV_TYPE_MAG_REFERENCED: + switch (dir) { + case IIO_EV_DIR_RISING: + ret = adxl345_is_act_inact_ac(st, ADXL345_ACTIVITY, &act_ac); + if (ret) + return ret; + return act_ac; + case IIO_EV_DIR_FALLING: + ret = adxl345_is_act_inact_ac(st, ADXL345_INACTIVITY, &inact_ac); + if (ret) + return ret; + return inact_ac; + default: + return -EINVAL; + } default: return -EINVAL; } @@ -1011,6 +1157,16 @@ static int adxl345_write_event_config(struct iio_dev *indio_dev, } case IIO_EV_TYPE_MAG: return adxl345_set_ff_en(st, state); + case IIO_EV_TYPE_MAG_REFERENCED: + switch (dir) { + case IIO_EV_DIR_RISING: + return adxl345_set_act_inact_ac(st, ADXL345_ACTIVITY, state); + case IIO_EV_DIR_FALLING: + return adxl345_set_act_inact_ac(st, ADXL345_INACTIVITY, state); + default: + return -EINVAL; + } + default: return -EINVAL; } From patchwork Mon Apr 14 18:42:45 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Lothar Rubusch X-Patchwork-Id: 14050885 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 29B842918EB; Mon, 14 Apr 2025 18:43: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=1744656185; cv=none; b=KyupqO3mPhZzGwMm7UbOiLVENy0I7IY6A3XrdCAhcsh8CnkDY4jClqbyl1Q6LkGFWNI9OIZkX3lYwqJ5agmbI8dBBma38ZbxXz0lOTom430c5O+7ynsu9NOY5kGY0LPfjLIrLp0Oo1xFbv3AsA2X53VWFBT3F+7/CYh/2B73sM4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744656185; c=relaxed/simple; bh=MYOFSonqaYrIg1QKuBtAZHQ4xCtuAWLMmC0mLSkiyws=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version:Content-Type; b=PhfnfAa/DbrW4+UKVG/8UKb0HmWaapgqZMaZaQQS6jA1zcSz8rBSxjBK6vXrtMIBdCAZ8afH4YI97HYUx7f/Z61kBnPMY1YWrymbLF+OZMPtMPidDY0GnADTGwfaliVKcJ+wfhjEhMvEiNPK8KPjI59sMqloTUcv+l/PmHE3vSM= 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=iitY5Vnh; 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="iitY5Vnh" Received: by mail-ej1-f44.google.com with SMTP id a640c23a62f3a-ac339f58631so77051066b.3; Mon, 14 Apr 2025 11:43:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1744656181; x=1745260981; 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=37QEzOsVCxWNGOZVk/Edp7QyuK+gRA8Xeta1nGCJGxI=; b=iitY5VnhlTSKEqxB7TPzJZb2+vyb0ZwyaV5ChIs3aSTpVe3H/5ibPhUszzZLiwhp2I VnNRNnck1nySbaiu3PwrQfbDGAJB02stNmE8xSFmoFWkAEJHkxIqw7+QsjwO3Lj1CYM/ gZvoOqnUHnftiutQF8ZivDnEQzlz5z5dZnUsLljpyC4C9UFSpRaNkY/ipfMDel95T2sq LuxthSGZAQtOzKdInfhoHex9zuYLbUEDtHstWZqQGdXBlTNGYzMDAsEfsPeCq5VBN7jF eCsNjR/8Wti+OAonz+YVBJgOD1q/8IqH2pq8lZ8E6zl/iDLp9kotQKY49Ni8VxPwuFu/ YXnQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1744656181; x=1745260981; 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=37QEzOsVCxWNGOZVk/Edp7QyuK+gRA8Xeta1nGCJGxI=; b=hqRiw9a36Tdv1wc5bERiIfkMwFWAPVf3I89YFauAgnmQJ8BIToC7Rox+Oi+IAUVI28 /EgIab68zG/bt+YmqXAbMFjir6TrWD3PVwhPAdyyzEmMoSwD3rt+nMKc0OMhWzxpqzPr TLSGZmgDJZYBooWbZgUpNOcTdN+m3yUaW9S5BzfROl2mR3ZsNtuQ3od1SiAE9pqCyH/K b1H85Or+EtIRBC0/5qctm7PJiqRIVeoionoxIr4zl61uj0Jy8pFT/12J98WqEz6rnbFW EWcdeEnjgO8rItVsza9n0rl/w+3kmPTFJjuIX2x8UsCqcdgh8URgMmfDKigKWiIii0XZ WV8Q== X-Forwarded-Encrypted: i=1; AJvYcCWsfU/gbSB7rpOymHy+HoJUtHbbOGh2dZ+bTWSB3axlsd9gqBTy0+tj4KhPy7yXzKuE1H+qiRWKScHwq1Q=@vger.kernel.org X-Gm-Message-State: AOJu0YxkKfUR9FZ64pyJ3sn1KXHUV3dFHnjNwIqVnLwTmzH7W0DQZuSX iIZ/CWi7n/Ef1vgaaBiDPa0HMpWIs6EcpAhb//lV4NeaeUSzCNLz+2dYQQ== X-Gm-Gg: ASbGncu29wLnnLNbkteVnmPdWP/cODm/V6Av1R2QJYma79HWRWHZxG6I+mx5QFfbJnX cyfZSH1bDSORT+ciudN117spmBHh3OGQqHokFqMtkqGyxC+zh/6Mgkq2bavxgs7LyNJ+fkhcUW8 gpKTn812juOljzAW+ieQY8EvhxrEbUmkXHGiHn5w91KIyc8EAFM48m5+651oA9YfnkClwHoAHTK LdjePfG3bN3hueD9hiCZkaxD0wQpUdGvwXvxfMYeBheTySjCB8Q3OeQ8XnCEMKHN89Hg4YFE9HR 13emiPlXKJajR9YwZp6NG1fGTp+bJKLXWN+1HPm4PufXNFIc3+pkclm/k+81QG/TAlVMAPQ3/QE 492MCl3Gdpq+86v7V7mY= X-Google-Smtp-Source: AGHT+IGdePt+pUxOuBCTf+QFjVTjQmXETUe5ykJSRKEBFrbbQIJ6M0ksXuYNHsJLKApPwzAp0ibU0g== X-Received: by 2002:a17:907:a58d:b0:aca:9de1:f88c with SMTP id a640c23a62f3a-acb13ebcdb2mr23996766b.10.1744656180638; Mon, 14 Apr 2025 11:43: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-acaa1bb3172sm946483466b.24.2025.04.14.11.42.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 14 Apr 2025 11:42: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 v6 11/11] docs: iio: add documentation for adxl345 driver Date: Mon, 14 Apr 2025 18:42:45 +0000 Message-Id: <20250414184245.100280-12-l.rubusch@gmail.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250414184245.100280-1-l.rubusch@gmail.com> References: <20250414184245.100280-1-l.rubusch@gmail.com> Precedence: bulk X-Mailing-List: linux-iio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 The documentation describes the ADXL345 driver, IIO interface, interface usage and configuration. Signed-off-by: Lothar Rubusch --- Documentation/iio/adxl345.rst | 429 ++++++++++++++++++++++++++++++++++ 1 file changed, 429 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..975e4645a857 --- /dev/null +++ b/Documentation/iio/adxl345.rst @@ -0,0 +1,429 @@ +.. SPDX-License-Identifier: GPL-2.0 + +=============== +ADXL345 driver +=============== + +This driver supports Analog Device's ADXL345/375 on SPI/I2C bus. + +1. Supported Devices +==================== + +* `ADXL345 `_ +* `ADXL375 `_ + +The ADXL345 is a generic purpose low power, 3-axis accelerometer with selectable +measurement ranges. The ADXL345 supports the ±2 g, ±4 g, ±8 g, and ±16 g ranges. + +2. Device Attributes +==================== + +Each IIO device, has a device folder under ``/sys/bus/iio/devices/iio:deviceX``, +where X is the IIO index of the device. Under these folders reside a set of +device files, depending on the characteristics and features of the hardware +device in questions. These files are consistently generalized and documented in +the IIO ABI documentation. + +The following table shows the ADXL345 related device files, found in the +specific device folder path ``/sys/bus/iio/devices/iio:deviceX``. + ++-------------------------------------------+----------------------------------------------------------+ +| 3-Axis Accelerometer related device files | Description | ++-------------------------------------------+----------------------------------------------------------+ +| in_accel_sampling_frequency | Currently selected sample rate. | ++-------------------------------------------+----------------------------------------------------------+ +| in_accel_sampling_frequency_available | Available sampling frequency configurations. | ++-------------------------------------------+----------------------------------------------------------+ +| in_accel_scale | Scale/range for the accelerometer channels. | ++-------------------------------------------+----------------------------------------------------------+ +| in_accel_scale_available | Available scale ranges for the accelerometer channel. | ++-------------------------------------------+----------------------------------------------------------+ +| in_accel_x_calibbias | Calibration offset for the X-axis accelerometer channel. | ++-------------------------------------------+----------------------------------------------------------+ +| in_accel_x_raw | Raw X-axis accelerometer channel value. | ++-------------------------------------------+----------------------------------------------------------+ +| in_accel_y_calibbias | y-axis acceleration offset correction | ++-------------------------------------------+----------------------------------------------------------+ +| in_accel_y_raw | Raw Y-axis accelerometer channel value. | ++-------------------------------------------+----------------------------------------------------------+ +| in_accel_z_calibbias | Calibration offset for the Z-axis accelerometer channel. | ++-------------------------------------------+----------------------------------------------------------+ +| in_accel_z_raw | Raw Z-axis accelerometer channel value. | ++-------------------------------------------+----------------------------------------------------------+ + +Channel Processed Values +------------------------- + +A channel value can be read from its _raw attribute. The value returned is the +raw value as reported by the devices. To get the processed value of the channel, +apply the following formula: + +.. code-block:: bash + + processed value = (_raw + _offset) * _scale + +Where _offset and _scale are device attributes. If no _offset attribute is +present, simply assume its value is 0. + ++-------------------------------------+---------------------------+ +| Channel type | Measurement unit | ++-------------------------------------+---------------------------+ +| Acceleration on X, Y, and Z axis | Meters per second squared | ++-------------------------------------+---------------------------+ + +Sensor Events +------------- + +Particular IIO events will be triggered by the corresponding interrupts. The +sensor driver supports no or one active INT line, where the sensor has two +possible INT IOs. Configure the used INT line in the devicetree. If no INT line +is configured, the sensor falls back to FIFO bypass mode and no events are +possible, only X, Y and Z axis measurements are possible. + +The following table shows the ADXL345 related device files, found in the +specific device folder path ``/sys/bus/iio/devices/iio:deviceX/events``. + ++---------------------------------------------+-----------------------------------------+ +| Event handle | Description | ++---------------------------------------------+-----------------------------------------+ +| in_accel_gesture_doubletap_en | Enable double tap detection on all axis | ++---------------------------------------------+-----------------------------------------+ +| in_accel_gesture_doubletap_reset_timeout | Double tap window in [us] | ++---------------------------------------------+-----------------------------------------+ +| in_accel_gesture_doubletap_tap2_min_delay | Double tap latent in [us] | ++---------------------------------------------+-----------------------------------------+ +| in_accel_gesture_singletap_timeout | Single tap duration in [us] | ++---------------------------------------------+-----------------------------------------+ +| in_accel_gesture_singletap_value | Single tap threshold value in 62.5/LSB | ++---------------------------------------------+-----------------------------------------+ +| in_accel_mag_falling_en | Enable free fall detection | ++---------------------------------------------+-----------------------------------------+ +| in_accel_mag_falling_period | Free fall time in [us] | ++---------------------------------------------+-----------------------------------------+ +| in_accel_mag_falling_value | Free fall threshold value in 62.5/LSB | ++---------------------------------------------+-----------------------------------------+ +| in_accel_mag_referenced_falling_en | Set 1 to AC-coupled inactivity, 0 for DC| ++---------------------------------------------+-----------------------------------------+ +| in_accel_mag_referenced_rising_en | Set 1 to AC-coupled activity, 0 for DC | ++---------------------------------------------+-----------------------------------------+ +| in_accel_x_thresh_falling_en | Enable inactivity detection on X axis | ++---------------------------------------------+-----------------------------------------+ +| in_accel_y_thresh_falling_en | Enable inactivity detection on Y axis | ++---------------------------------------------+-----------------------------------------+ +| in_accel_z_thresh_falling_en | Enable inactivity detection on Z axis | ++---------------------------------------------+-----------------------------------------+ +| in_accel_thresh_falling_period | Inactivity time in seconds | ++---------------------------------------------+-----------------------------------------+ +| in_accel_thresh_falling_value | Inactivity threshold value in 62.5/LSB | ++---------------------------------------------+-----------------------------------------+ +| in_accel_x_thresh_rising_en | Enable activity detection on X axis | ++---------------------------------------------+-----------------------------------------+ +| in_accel_y_thresh_rising_en | Enable activity detection on Y axis | ++---------------------------------------------+-----------------------------------------+ +| in_accel_z_thresh_rising_en | Enable activity detection on Z axis | ++---------------------------------------------+-----------------------------------------+ +| in_accel_thresh_rising_value | Activity threshold value in 62.5/LSB | ++---------------------------------------------+-----------------------------------------+ +| in_accel_x_gesture_singletap_en | Enable single tap detection on X axis | ++---------------------------------------------+-----------------------------------------+ +| in_accel_y_gesture_singletap_en | Enable single tap detection on Y axis | ++---------------------------------------------+-----------------------------------------+ +| in_accel_z_gesture_singletap_en | Enable single tap detection on Z axis | ++---------------------------------------------+-----------------------------------------+ + +Find a detailed description of a particular functionality in the sensor +datasheet. + +Setting the **ODR** explicitly will result in estimated adjusted default values +for the inactivity time detection, where higher frequencies shall default to +longer wait periods, and vice versa. It is also possible to explicetly +configure inactivity wait times, if the defaulting approach does not match +application requirements. Setting 0 here, will fall back to default setting. + +The **g range** configuration also tries to estimate activity and inactivity +thresholds when switching to another g range. The default range will be +factorized by the relation of old range divided by new range. The value never +becomes 0 and will be at least 1 and at most 255 i.e. 62.5g/LSB according to +the datasheet. Nevertheless activity and inactivity thresholds can be +overwritten by explicit values. + +When **activity** and **inactivity** events are enabled, the driver automatically +will implement its hysteresis solution by setting link bit and autosleep bit. +The link bit serially links the activity and inactivity functions. On the other +side, the autosleep function switches the sensor to sleep mode if the +inactivity function is enabled. This will reduce current consumption to the +sub-12.5Hz rate. Inactivity time can be configured between 1s and 255s. When 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 taken +as a reference value. New samples are then compared to this reference value. +Note, ac-coupling and dc-coupling are individually set for activity and/or +inactivity detection. Activity and inactivity detection are dependent on the +direction, i.e. the x/y/z axis where this driver generally enables all +directions. Also, the direction settings are particular to activity and +inactivity detection, respectively. + +**Single tap** detection can be configured according to the datasheet by specifying +threshold and duration. If only the single tap is in use, the single tap +interrupt is triggered when the acceleration goes above threshold (i.e. DUR +start) and below the threshold, as long as duration is not exceeded. If single +tap and double tap are in use, the single tap is triggered when the doulbe tap +event has been either validated or invalidated. + +For **double tap** configure additionally window and latency in [us]. Latency +starts counting when the single tap goes below threshold and is a waiting +period, any spikes here are ignored for double tap detection. After latency, +the window starts. Any rise above threshold, with a consequent fall below +threshold within window time, rises a double tap signal when going below +threshold. + +Double tap event detection is best described in the datasheet. After a +single tap event was detected, a double tap event can be detected. Therefore the +signal must match several criteria, and detection can also considered invalid +for three reasons: +* If the **suppress bit** is set and when still in the tap latency period, any +measurement of acceleration spike above the tap threshold invalidates double tap +detection immediately, i.e. during latency must not occur spikes for double tap +detection when the suppress bit is set. +* A double tap event is considered invalid, if acceleration lies above the +threshold at the start of the window time for double tap. +* Additionally, double tap detection can be considered invalid, if an +acceleration exceeds the time limit for taps, set by duration register. +Note, since for double tap the same duration counts, i.e. when rising above +threshold, a consequent falling below threshold has to be within duration time. +Also note, the suppress bit is generally set when double tap is enabled. + +A **free fall** event will be detected if the signal goes below the configured +threshold, for the configured time [us]. + +Note, that activity/inactivy, as also freefall is recommended for 12.5 Hz ODR +up to 400 Hz. + +Usage Examples +-------------- + +Show device name: + +.. code-block:: bash + + root:/sys/bus/iio/devices/iio:device0> cat name + adxl345 + +Show accelerometer channels value: + +.. code-block:: bash + + root:/sys/bus/iio/devices/iio:device0> cat in_accel_x_raw + -1 + root:/sys/bus/iio/devices/iio:device0> cat in_accel_y_raw + 2 + root:/sys/bus/iio/devices/iio:device0> cat in_accel_z_raw + -253 + +Set calibration offset for accelerometer channels: + +.. code-block:: bash + + root:/sys/bus/iio/devices/iio:device0> cat in_accel_x_calibbias + 0 + + root:/sys/bus/iio/devices/iio:device0> echo 50 > in_accel_x_calibbias + root:/sys/bus/iio/devices/iio:device0> cat in_accel_x_calibbias + 50 + +Given the 13-bit full resolution, the available ranges are calculated by the +following forumla: + +.. code-block:: bash + + (g * 2 * 9.80665) / (2^(resolution) - 1) * 100; for g := 2|4|8|16 + +Scale range configuration: + +.. code-block:: bash + + root:/sys/bus/iio/devices/iio:device0> cat ./in_accel_scale + 0.478899 + root:/sys/bus/iio/devices/iio:device0> cat ./in_accel_scale_available + 0.478899 0.957798 1.915595 3.831190 + + root:/sys/bus/iio/devices/iio:device0> echo 1.915595 > ./in_accel_scale + root:/sys/bus/iio/devices/iio:device0> cat ./in_accel_scale + 1.915595 + +Set output data rate (ODR): + +.. code-block:: bash + + root:/sys/bus/iio/devices/iio:device0> cat ./in_accel_sampling_frequency + 200.000000 + + root:/sys/bus/iio/devices/iio:device0> cat ./in_accel_sampling_frequency_available + 0.097000 0.195000 0.390000 0.781000 1.562000 3.125000 6.250000 12.500000 25.000000 50.000000 100.000000 200.000000 400.000000 800.000000 1600.000000 3200.000000 + + root:/sys/bus/iio/devices/iio:device0> echo 1.562000 > ./in_accel_sampling_frequency + root:/sys/bus/iio/devices/iio:device0> cat ./in_accel_sampling_frequency + 1.562000 + +Configure one or several events: + +.. code-block:: bash + + root:> cd /sys/bus/iio/devices/iio:device0 + + root:/sys/bus/iio/devices/iio:device0> echo 1 > ./buffer0/in_accel_x_en + root:/sys/bus/iio/devices/iio:device0> echo 1 > ./buffer0/in_accel_y_en + root:/sys/bus/iio/devices/iio:device0> echo 1 > ./buffer0/in_accel_z_en + + root:/sys/bus/iio/devices/iio:device0> echo 1 > ./scan_elements/in_accel_x_en + root:/sys/bus/iio/devices/iio:device0> echo 1 > ./scan_elements/in_accel_y_en + root:/sys/bus/iio/devices/iio:device0> echo 1 > ./scan_elements/in_accel_z_en + + root:/sys/bus/iio/devices/iio:device0> echo 14 > ./in_accel_x_calibbias + root:/sys/bus/iio/devices/iio:device0> echo 2 > ./in_accel_y_calibbias + root:/sys/bus/iio/devices/iio:device0> echo -250 > ./in_accel_z_calibbias + + root:/sys/bus/iio/devices/iio:device0> echo 24 > ./buffer0/length + + ## activity, threshold [62.5/LSB] + root:/sys/bus/iio/devices/iio:device0> echo 6 > ./events/in_accel_thresh_rising_value + + ## inactivity, threshold, [62.5/LSB] + root:/sys/bus/iio/devices/iio:device0> echo 4 > ./events/in_accel_thresh_falling_value + + ## inactivity, time [s] + root:/sys/bus/iio/devices/iio:device0> echo 3 > ./events/in_accel_thresh_falling_period + + ## singletap, threshold + root:/sys/bus/iio/devices/iio:device0> echo 35 > ./events/in_accel_gesture_singletap_value + + ## singletap, duration [us] + root:/sys/bus/iio/devices/iio:device0> echo 0.001875 > ./events/in_accel_gesture_singletap_timeout + + ## doubletap, window [us] + root:/sys/bus/iio/devices/iio:device0> echo 0.025 > ./events/in_accel_gesture_doubletap_reset_timeout + + ## doubletap, latent [us] + root:/sys/bus/iio/devices/iio:device0> echo 0.025 > ./events/in_accel_gesture_doubletap_tap2_min_delay + + ## freefall, threshold [62.5/LSB] + root:/sys/bus/iio/devices/iio:device0> echo 8 > ./events/in_accel_mag_falling_value + + ## freefall, time [ms] + root:/sys/bus/iio/devices/iio:device0> echo 1.25 > ./events/in_accel_mag_falling_period + + ## activity, enable + root:/sys/bus/iio/devices/iio:device0> echo 1 > ./events/in_accel_thresh_rising_en + + ## inactivity, enable + root:/sys/bus/iio/devices/iio:device0> echo 1 > ./events/in_accel_thresh_falling_en + + ## freefall, enable + root:/sys/bus/iio/devices/iio:device0> echo 1 > ./events/in_accel_mag_falling_en + + ## singletap, enable + root:/sys/bus/iio/devices/iio:device0> echo 1 > ./events/in_accel_x_gesture_singletap_en + root:/sys/bus/iio/devices/iio:device0> echo 1 > ./events/in_accel_y_gesture_singletap_en + root:/sys/bus/iio/devices/iio:device0> echo 1 > ./events/in_accel_z_gesture_singletap_en + + ## doubletap, enable + root:/sys/bus/iio/devices/iio:device0> echo 1 > ./events/in_accel_gesture_doubletap_en + +Verify incoming events: + +.. code-block:: bash + + root:# iio_event_monitor adxl345 + Found IIO device with name adxl345 with device number 0 + Event: time: 1739063415957073383, type: accel(z), channel: 0, evtype: thresh, direction: rising + Event: time: 1739063415963770218, type: accel(z), channel: 0, evtype: thresh, direction: rising + Event: time: 1739063416002563061, type: accel(z), channel: 0, evtype: gesture, direction: singletap + Event: time: 1739063426271128739, type: accel(x|y|z), channel: 0, evtype: thresh, direction: falling + Event: time: 1739063436539080713, type: accel(x|y|z), channel: 0, evtype: thresh, direction: falling + Event: time: 1739063438357970381, type: accel(z), channel: 0, evtype: thresh, direction: rising + Event: time: 1739063446726161586, type: accel(z), channel: 0, evtype: thresh, direction: rising + Event: time: 1739063446727892670, type: accel(z), channel: 0, evtype: thresh, direction: rising + Event: time: 1739063446743019768, type: accel(z), channel: 0, evtype: thresh, direction: rising + Event: time: 1739063446744650696, type: accel(z), channel: 0, evtype: thresh, direction: rising + Event: time: 1739063446763559386, type: accel(z), channel: 0, evtype: gesture, direction: singletap + Event: time: 1739063448818126480, type: accel(x|y|z), channel: 0, evtype: thresh, direction: falling + ... + +Activity and inactivity belong together and indicate state changes as follows + +.. 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, evtype: thresh, direction: rising + + Event: time: 1744648057724775499, type: accel(x|y|z), channel: 0, evtype: thresh, direction: falling + ... + +3. Device Buffers +================= + +This driver supports IIO buffers. + +All devices support retrieving the raw acceleration and temperature measurements +using buffers. + +Usage examples +-------------- + +Select channels for buffer read: + +.. code-block:: bash + + root:/sys/bus/iio/devices/iio:device0> echo 1 > scan_elements/in_accel_x_en + root:/sys/bus/iio/devices/iio:device0> echo 1 > scan_elements/in_accel_y_en + root:/sys/bus/iio/devices/iio:device0> echo 1 > scan_elements/in_accel_z_en + +Set the number of samples to be stored in the buffer: + +.. code-block:: bash + + root:/sys/bus/iio/devices/iio:device0> echo 10 > buffer/length + +Enable buffer readings: + +.. code-block:: bash + + root:/sys/bus/iio/devices/iio:device0> echo 1 > buffer/enable + +Obtain buffered data: + +.. code-block:: bash + + root:> iio_readdev -b 16 -s 1024 adxl345 | hexdump -d + WARNING: High-speed mode not enabled + 0000000 00003 00012 00013 00005 00010 00011 00005 00011 + 0000010 00013 00004 00012 00011 00003 00012 00014 00007 + 0000020 00011 00013 00004 00013 00014 00003 00012 00013 + 0000030 00004 00012 00013 00005 00011 00011 00005 00012 + 0000040 00014 00005 00012 00014 00004 00010 00012 00004 + 0000050 00013 00011 00003 00011 00012 00005 00011 00013 + 0000060 00003 00012 00012 00003 00012 00012 00004 00012 + 0000070 00012 00003 00013 00013 00003 00013 00012 00005 + 0000080 00012 00013 00003 00011 00012 00005 00012 00013 + 0000090 00003 00013 00011 00005 00013 00014 00003 00012 + 00000a0 00012 00003 00012 00013 00004 00012 00015 00004 + 00000b0 00014 00011 00003 00014 00013 00004 00012 00011 + 00000c0 00004 00012 00013 00004 00014 00011 00004 00013 + 00000d0 00012 00002 00014 00012 00005 00012 00013 00005 + 00000e0 00013 00013 00003 00013 00013 00005 00012 00013 + 00000f0 00004 00014 00015 00005 00012 00011 00005 00012 + ... + +See ``Documentation/iio/iio_devbuf.rst`` for more information about how buffered +data is structured. + +4. IIO Interfacing Tools +======================== + +See ``Documentation/iio/iio_tools.rst`` for the description of the available IIO +interfacing tools.