From nobody Tue Apr 23 21:37:18 2024 Delivered-To: importer2@patchew.org Received-SPF: pass (zohomail.com: domain of vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; envelope-from=linux-kernel-owner@vger.kernel.org; helo=vger.kernel.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail(p=none dis=none) header.from=gmail.com Return-Path: Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mx.zohomail.com with SMTP id 1644824311209131.41822607228335; Sun, 13 Feb 2022 23:38:31 -0800 (PST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241448AbiBNHig (ORCPT ); Mon, 14 Feb 2022 02:38:36 -0500 Received: from mxb-00190b01.gslb.pphosted.com ([23.128.96.19]:55666 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229529AbiBNHia (ORCPT ); Mon, 14 Feb 2022 02:38:30 -0500 Received: from mail-ej1-x634.google.com (mail-ej1-x634.google.com [IPv6:2a00:1450:4864:20::634]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 239264F47F; Sun, 13 Feb 2022 23:38:23 -0800 (PST) Received: by mail-ej1-x634.google.com with SMTP id a8so35538447ejc.8; Sun, 13 Feb 2022 23:38:23 -0800 (PST) Received: from demon-pc.localdomain ([188.24.58.131]) by smtp.gmail.com with ESMTPSA id 9sm2480065ejd.184.2022.02.13.23.38.20 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 13 Feb 2022 23:38:21 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=AVMu6NN3biChFR5UuxImcxGSWWGJG/KG7InEx8tN/zM=; b=IPJ5L/Gd4eaUTATgSsFFcNgdogHy+3PeWddDTcM6RMYnTojO8nmAYe7DljsIrAzQi7 i6Xq60F/Pxt9k7ZOk+UNVayYR5d+XRZEWfTHX4xqxF3NJeSWi2Ba3sXXw1T2vMJ7P/k2 0q2yOtYrF0KsL7CqQ1tilLcKdjZIOlRwwrbAdhBQlaBN67Jsh/4AXatn4i/PS4Q8JaFZ Xk3o5MhHB45kSupMfzS4bbVM4XeZWBRsDr4HHvKhy1mvgFGUlCXpGbj9MqsOOg7mNmyh HqHuq3rMqOhyQH6KQejnupSrrDv7sThFB11ck/fYmCvMTihbse0366OMsDRigwHyLm1L hK4A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=AVMu6NN3biChFR5UuxImcxGSWWGJG/KG7InEx8tN/zM=; b=NrhgAzS/DQ9i9Op8MsYy93b2x4qVyGVfvI4wlpRtl35B9dirrCUJjbOiVZ525TfPS2 4n8zVAXU5ufgkC0a3TWgX1K29fNFSEcW8+nlzxrz56OCW5V+4RT+5ZhInVcxpEMXzX34 RjstpmJhYH8NgPWiqfwFE1R+4tXMjHINKK0+9HgadoGry82xKYmBgmT9CdUfsRge8o6s GMndHts+ODkHV+S1oAtI0FXO5XBmdMsFciDAsus1+O84pxKKRR/47ZtjFmwHeZ5siq2y NmDkny7ZpWgk3sPOBV6XRbXEjoGHyYo5bIG+mgj6N+mO72suMcxjkSNxQ4hxvq+BSxeJ JV9A== X-Gm-Message-State: AOAM533HfKq3ustlt7jyAABbc9XzrbQSHLpwG3WHoZfi53Q0vFqJ0dsA GOg97vPZY2jbq2/l2l6Dcdg= X-Google-Smtp-Source: ABdhPJyLQdlZaKqPwB9HMGZNonoU8F290JfXnTh8DZkkz1YHIEXvNVVeuSBR8STeaI9T4YvrnHaKgw== X-Received: by 2002:a17:907:970f:: with SMTP id jg15mr10393921ejc.705.1644824301740; Sun, 13 Feb 2022 23:38:21 -0800 (PST) From: Cosmin Tanislav X-Google-Original-From: Cosmin Tanislav Cc: cosmin.tanislav@analog.com, demonsingur@gmail.com, Lars-Peter Clausen , Michael Hennerich , Rob Herring , linux-iio@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v5 1/5] iio: introduce mag_referenced Date: Mon, 14 Feb 2022 09:38:06 +0200 Message-Id: <20220214073810.781016-2-cosmin.tanislav@analog.com> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220214073810.781016-1-cosmin.tanislav@analog.com> References: <20220214073810.781016-1-cosmin.tanislav@analog.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net To: unlisted-recipients:; (no To-header on input) Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZM-MESSAGEID: 1644824312843100001 Content-Type: text/plain; charset="utf-8" Some accelerometers that support activity and inactivity events also support a referenced mode, in which the gravitational acceleration is taken as a point of reference before comparing the acceleration to the specified activity and inactivity magnitude. For example, in the case of the ADXL367, for activity detection, the formula is: abs(acceleration - reference) > magnitude Add a new event type that makes this behavior clear. Signed-off-by: Cosmin Tanislav --- drivers/iio/industrialio-event.c | 1 + include/uapi/linux/iio/types.h | 1 + tools/iio/iio_event_monitor.c | 1 + 3 files changed, 3 insertions(+) diff --git a/drivers/iio/industrialio-event.c b/drivers/iio/industrialio-ev= ent.c index d0732eac0f0a..ce8b102ce52f 100644 --- a/drivers/iio/industrialio-event.c +++ b/drivers/iio/industrialio-event.c @@ -230,6 +230,7 @@ static const char * const iio_ev_type_text[] =3D { [IIO_EV_TYPE_THRESH_ADAPTIVE] =3D "thresh_adaptive", [IIO_EV_TYPE_MAG_ADAPTIVE] =3D "mag_adaptive", [IIO_EV_TYPE_CHANGE] =3D "change", + [IIO_EV_TYPE_MAG_REFERENCED] =3D "mag_referenced", }; =20 static const char * const iio_ev_dir_text[] =3D { diff --git a/include/uapi/linux/iio/types.h b/include/uapi/linux/iio/types.h index 48c13147c0a8..472cead10d8d 100644 --- a/include/uapi/linux/iio/types.h +++ b/include/uapi/linux/iio/types.h @@ -104,6 +104,7 @@ enum iio_event_type { IIO_EV_TYPE_THRESH_ADAPTIVE, IIO_EV_TYPE_MAG_ADAPTIVE, IIO_EV_TYPE_CHANGE, + IIO_EV_TYPE_MAG_REFERENCED, }; =20 enum iio_event_direction { diff --git a/tools/iio/iio_event_monitor.c b/tools/iio/iio_event_monitor.c index b94a16ba5c6c..2f4581658859 100644 --- a/tools/iio/iio_event_monitor.c +++ b/tools/iio/iio_event_monitor.c @@ -68,6 +68,7 @@ static const char * const iio_ev_type_text[] =3D { [IIO_EV_TYPE_THRESH_ADAPTIVE] =3D "thresh_adaptive", [IIO_EV_TYPE_MAG_ADAPTIVE] =3D "mag_adaptive", [IIO_EV_TYPE_CHANGE] =3D "change", + [IIO_EV_TYPE_MAG_REFERENCED] =3D "mag_referenced", }; =20 static const char * const iio_ev_dir_text[] =3D { --=20 2.35.1 From nobody Tue Apr 23 21:37:18 2024 Delivered-To: importer2@patchew.org Received-SPF: pass (zohomail.com: domain of vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; envelope-from=linux-kernel-owner@vger.kernel.org; helo=vger.kernel.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail(p=none dis=none) header.from=gmail.com Return-Path: Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mx.zohomail.com with SMTP id 1644824316416251.40864844408247; Sun, 13 Feb 2022 23:38:36 -0800 (PST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241478AbiBNHim (ORCPT ); Mon, 14 Feb 2022 02:38:42 -0500 Received: from mxb-00190b01.gslb.pphosted.com ([23.128.96.19]:55694 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241412AbiBNHic (ORCPT ); Mon, 14 Feb 2022 02:38:32 -0500 Received: from mail-ej1-x630.google.com (mail-ej1-x630.google.com [IPv6:2a00:1450:4864:20::630]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 915D559A4C; Sun, 13 Feb 2022 23:38:24 -0800 (PST) Received: by mail-ej1-x630.google.com with SMTP id jg20so10610428ejc.3; Sun, 13 Feb 2022 23:38:24 -0800 (PST) Received: from demon-pc.localdomain ([188.24.58.131]) by smtp.gmail.com with ESMTPSA id 9sm2480065ejd.184.2022.02.13.23.38.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 13 Feb 2022 23:38:22 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=+mR95J2LT/Gbe3zVkCuvHD8OzNfodUwOt0VFxheiVPs=; b=oq+uj0YAwVucwdN6fruQ96UOBzwgAnTQQtA6BQAI5pqexaziARwDENWa9kRzSdLsle uYg+uRFpb7u4xEtuQxQJ0PO50i63+Qe7kz6fWTK812KY4qZI18ckcmmH+h0ktsv2M+iI RwbJKRRpH1caIK8BJmmhKh9ljXx31wyAhaeBG6fTi6hipDtda+s0SS/y83qLjDJhVCeI LhwLBAH4UNPNNvFXQbep37Lo5lDt/F+WJZBfWCu+yJCA485IujA7IX73zl64jLU/LMzY ZYp+VxNW8rP9IZD16x8muxRwEOkYXgSR9Xj2H4fSiIPSfG+Lu1Zw8NriyztlxmvnNNvx b3cA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=+mR95J2LT/Gbe3zVkCuvHD8OzNfodUwOt0VFxheiVPs=; b=2uWFc8hNeCGiPVSEQMezylj5kq6P29Edu8OZX8SJyrGq/YYDqP1xcOI4JUVdWH25Wn tU7KZgJZ9U1LifcdTug6MHb5N0fi/ftbbAeU16mVMZ9mocwn3LghrbMFFtzAN74UhDcA yotkbKM6TXRSZCMIL5mhN14m5xc1Zuq4oQmFxxHhTUbWSxHrGhezoHtR5+1oXB8NDE2c qkkjLKMVE7HzGlCljnyg5sxkRFRQkOnI1GWDleCAqusgDxEvCJ1GdSbYESc2vh5hVvEu 2ASbfUKEvFMLvlRsjdsftw4kB95JvZP/sHEsOJbkxU3bkFo3NccWZlbBWNidDtYV5ePx 5EsA== X-Gm-Message-State: AOAM533KXId1Nm7KuIkXU9W/62HMjBEy8Tz0VFDKjFLJNuinYBOZYyyf P8vRd+w0hSMxUmO3lBhif/alFJCnT/o= X-Google-Smtp-Source: ABdhPJzSfi774tIJeU3md2VRN1w6gYZZ9dtEmOK96422+bpuCIn88GiYEJybyPuHKniaDqW+Vc/x+g== X-Received: by 2002:a17:907:2d11:: with SMTP id gs17mr10125423ejc.360.1644824303095; Sun, 13 Feb 2022 23:38:23 -0800 (PST) From: Cosmin Tanislav X-Google-Original-From: Cosmin Tanislav Cc: cosmin.tanislav@analog.com, demonsingur@gmail.com, Lars-Peter Clausen , Michael Hennerich , Rob Herring , linux-iio@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v5 2/5] iio: ABI: document mag_referenced Date: Mon, 14 Feb 2022 09:38:07 +0200 Message-Id: <20220214073810.781016-3-cosmin.tanislav@analog.com> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220214073810.781016-1-cosmin.tanislav@analog.com> References: <20220214073810.781016-1-cosmin.tanislav@analog.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net To: unlisted-recipients:; (no To-header on input) Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZM-MESSAGEID: 1644824316917100003 Content-Type: text/plain; charset="utf-8" Some accelerometers that support activity and inactivity events also support a referenced mode, in which the gravitational acceleration is taken as a point of reference before comparing the acceleration to the specified activity and inactivity magnitude. For example, in the case of the ADXL367, for activity detection, the formula is: abs(acceleration - reference) > magnitude Add a new event type that makes this behavior clear. Signed-off-by: Cosmin Tanislav --- Documentation/ABI/testing/sysfs-bus-iio | 26 +++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/te= sting/sysfs-bus-iio index c551301b33f1..41c1e3e1bf30 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio +++ b/Documentation/ABI/testing/sysfs-bus-iio @@ -1213,6 +1213,32 @@ Description: number or direction is not specified, applies to all channels of this type. =20 +What: /sys/.../iio:deviceX/events/in_accel_mag_referenced_en +What: /sys/.../iio:deviceX/events/in_accel_mag_referenced_rising_en +What: /sys/.../iio:deviceX/events/in_accel_mag_referenced_falling_en +What: /sys/.../iio:deviceX/events/in_accel_y_mag_referenced_en +What: /sys/.../iio:deviceX/events/in_accel_y_mag_referenced_rising_en +What: /sys/.../iio:deviceX/events/in_accel_y_mag_referenced_falling_en +KernelVersion: 5.18 +Contact: linux-iio@vger.kernel.org +Description: + Similar to in_accel_mag[_y][_rising|_falling]_en, but the event + value is relative to a reference magnitude. The reference magnitude + includes the graviational acceleration. + +What: /sys/.../iio:deviceX/events/in_accel_mag_referenced_value +What: /sys/.../iio:deviceX/events/in_accel_mag_referenced_rising_value +What: /sys/.../iio:deviceX/events/in_accel_mag_referenced_falling_value +What: /sys/.../iio:deviceX/events/in_accel_y_mag_referenced_value +What: /sys/.../iio:deviceX/events/in_accel_y_mag_referenced_rising_value +What: /sys/.../iio:deviceX/events/in_accel_y_mag_referenced_falling_value +KernelVersion: 5.18 +Contact: linux-iio@vger.kernel.org +Description: + The value to which the reference magnitude of the channel is + compared. If the axis is not specified, it applies to all channels + of this type. + What: /sys/.../events/in_steps_change_en KernelVersion: 4.0 Contact: linux-iio@vger.kernel.org --=20 2.35.1 From nobody Tue Apr 23 21:37:18 2024 Delivered-To: importer2@patchew.org Received-SPF: pass (zohomail.com: domain of vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; envelope-from=linux-kernel-owner@vger.kernel.org; helo=vger.kernel.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail(p=none dis=none) header.from=gmail.com Return-Path: Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mx.zohomail.com with SMTP id 16448243178681016.7977556393155; Sun, 13 Feb 2022 23:38:37 -0800 (PST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241491AbiBNHim (ORCPT ); Mon, 14 Feb 2022 02:38:42 -0500 Received: from mxb-00190b01.gslb.pphosted.com ([23.128.96.19]:55698 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241424AbiBNHic (ORCPT ); Mon, 14 Feb 2022 02:38:32 -0500 Received: from mail-ej1-x62d.google.com (mail-ej1-x62d.google.com [IPv6:2a00:1450:4864:20::62d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8FA6B5A09D; Sun, 13 Feb 2022 23:38:25 -0800 (PST) Received: by mail-ej1-x62d.google.com with SMTP id p9so12656855ejd.6; Sun, 13 Feb 2022 23:38:25 -0800 (PST) Received: from demon-pc.localdomain ([188.24.58.131]) by smtp.gmail.com with ESMTPSA id 9sm2480065ejd.184.2022.02.13.23.38.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 13 Feb 2022 23:38:23 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=qnfc/m4b0eUi8rt1+Lbiend5PrPGvJuYvFCo7+VTsrY=; b=lFFqf/BNhc55z+4ipzgclhbpaTld4n6BcYri9CBiQLcOlVHI6wXALzDx3hqaolL/Eh 2Wu4BI2lKadB+Ya0jovLoInXMtJvIInJ2jUzS707lBawzQkf8zXzPspv3rGkxKTDo2NB wXoUBJtrG/RI9d8PjEpXeW1N7X58/ZCVBqp2+hjCJC4XvCH3kAz96wQVl9eNxjRuwKyk M7UTRIYK/GsbAvaXwt3uuPcfDIJBsNJXyCHlqTYDS6+AmaY200AoW17vjTvP+9Z9+HS4 8vyaOI1++Aj2h2pyLqWWUNX7PO5MznY7meluY/f1GC5pumN3xdeJ8ts7FawmNYajgrs9 9TUQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=qnfc/m4b0eUi8rt1+Lbiend5PrPGvJuYvFCo7+VTsrY=; b=jkfV1QTO2hAjdegq1qj9sTyifj6mSVYaesf20jLENO3FcDJWkFsuWUx+ladjWQuuaG 7PM8SgPiXe89eg5UytmbeC6ka1B2zACsmB9Y709GVHIs/xkJxKoLvsR4OMcDnxrWQJHE rCH6C4l+tOMOp3TkgjKEDaLgpDQdgz67E3HeO7o07bOV8hg5hio6pUUdL9LJvPO213hg gDPTLKBzXSJT34YOi1b2MUk58Z6qIjbbxJ5na6BUysirZAXjgPnJzSHy15ZPAOVEXVx/ FU0wfQKewzWY6DTSH68ZLQ9RxmW7ETQf8tvn3/eHKHiWYLkwLTVKMNSjL9EcF58nfi/z q9OA== X-Gm-Message-State: AOAM533ac93VHCc2J4gUNlds0RqPeqMWCM6wCbtU36BFcqNttr/mtcY6 6kIX+hMEGPMOxe+RrWwheP0= X-Google-Smtp-Source: ABdhPJwvUpUJ3CJFQU9+VtaM2idE0STA5Ev3Nc7FdHO4yFI+pijE6r+VFV921GgXF1zuyHGg0W8vOQ== X-Received: by 2002:a17:907:8a1f:: with SMTP id sc31mr7529306ejc.651.1644824304224; Sun, 13 Feb 2022 23:38:24 -0800 (PST) From: Cosmin Tanislav X-Google-Original-From: Cosmin Tanislav Cc: cosmin.tanislav@analog.com, demonsingur@gmail.com, Lars-Peter Clausen , Michael Hennerich , Rob Herring , linux-iio@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v5 3/5] iio: ABI: add note about configuring other attributes during buffer capture Date: Mon, 14 Feb 2022 09:38:08 +0200 Message-Id: <20220214073810.781016-4-cosmin.tanislav@analog.com> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220214073810.781016-1-cosmin.tanislav@analog.com> References: <20220214073810.781016-1-cosmin.tanislav@analog.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net To: unlisted-recipients:; (no To-header on input) Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZM-MESSAGEID: 1644824318917100007 Content-Type: text/plain; charset="utf-8" It might be impossible to configure other attributes (e.g.: events, scale, sampling rate) if they impact the currently active buffer capture session. On ADXL367, writing to register before 0x2E requires the device to be placed in standby mode, otherwise the changes might be effective for only part of a measurement. To ensure this requirement, the configuration attributes of the IIO device try to claim direct mode before switching to standby mode. During a buffer capture, direct mode cannot be claimed, and the attribute write callback returns -EBUSY. Describe this behavior in the buffer/enable attribute description. Signed-off-by: Cosmin Tanislav --- Documentation/ABI/testing/sysfs-bus-iio | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/te= sting/sysfs-bus-iio index 41c1e3e1bf30..bc98453bdade 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio +++ b/Documentation/ABI/testing/sysfs-bus-iio @@ -1278,6 +1278,10 @@ Description: Actually start the buffer capture up. Will start trigger if first device and appropriate. =20 + Note that it might be impossible to configure other attributes, + (e.g.: events, scale, sampling rate) if they impact the currently + active buffer capture session. + What: /sys/bus/iio/devices/iio:deviceX/bufferY KernelVersion: 5.11 Contact: linux-iio@vger.kernel.org --=20 2.35.1 From nobody Tue Apr 23 21:37:18 2024 Delivered-To: importer2@patchew.org Received-SPF: pass (zohomail.com: domain of vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; envelope-from=linux-kernel-owner@vger.kernel.org; helo=vger.kernel.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail(p=none dis=none) header.from=gmail.com Return-Path: Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mx.zohomail.com with SMTP id 164482431469916.793519960455797; Sun, 13 Feb 2022 23:38:34 -0800 (PST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241470AbiBNHik (ORCPT ); Mon, 14 Feb 2022 02:38:40 -0500 Received: from mxb-00190b01.gslb.pphosted.com ([23.128.96.19]:55726 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232225AbiBNHie (ORCPT ); Mon, 14 Feb 2022 02:38:34 -0500 Received: from mail-ej1-x631.google.com (mail-ej1-x631.google.com [IPv6:2a00:1450:4864:20::631]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id EACF85A0AE; Sun, 13 Feb 2022 23:38:26 -0800 (PST) Received: by mail-ej1-x631.google.com with SMTP id hw13so7059026ejc.9; Sun, 13 Feb 2022 23:38:26 -0800 (PST) Received: from demon-pc.localdomain ([188.24.58.131]) by smtp.gmail.com with ESMTPSA id 9sm2480065ejd.184.2022.02.13.23.38.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 13 Feb 2022 23:38:25 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=f8SXCNeboPV5p4WZMz4UAaCSfT79i5ySX42XkzZvpOo=; b=pwvSmwB22CdJbJGvcAxNV3UWj1yoL5L4cGkij5LLzQGZLX96vcA1NviuiGOansGty+ Q49YPUsAsiewd1FaAqZ9FRjPbZZXKm1kmiqJ4eFUb3GnkGg3cwnneKWXzXPQuLm5RRX3 txcZ4pdS/EzrcWlVA5yGH+sursPyNtUmiS4AolHftAjDUdAzNWkm95jFTaOcEVAhhkNN 1VdwzFmXmU7yeQnJfKVZ5FDKNXU6YE5HjNqiCKv+yqRIj6FEgnxixV3TkJmZI4KSfckC vR2PAx8luXNwIa/RAXOlsytOz0pbCA9HCaWmBUC2pDGcUUzyNSAqkzlglBVLbu8wIQ4b GzJw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=f8SXCNeboPV5p4WZMz4UAaCSfT79i5ySX42XkzZvpOo=; b=78okRE0lB3LLCtBI7Y/Mxp7T2hNjcQOMSf9iSLPcUojNWG4YoL4xpq0UsN1n0k5bqC eWpYaxEc+hxlP0jq/Hv5vprQQnlaa9Z7U/OVboC0efmzDcvv9yVyGPFCUWy6n5ZhVdMj t50kHs9EKaFqHeRUjm99eXCZEJ5LlR/qCwG5L6ouiSZDHYJ3uZUJJJh4DoaQ3IKRu030 MvSI/qO/N3m4A2sqKmAGQiPVQpZGV25eegA9oV3zWAmvlg1GFxE9/Q6ra52fHt+fGLzL Kq20RnzwqLirpqM5J72pfiehcuc0pYZSdviOs1vwieTRR07EOAJJmEy1B1yJLtxiQ8zp Qg+w== X-Gm-Message-State: AOAM531PKOqjQIiBAIeDT3x6hz6fBZBX+A6oqrWDnN8zLfi3uqlgT32S j4NOukSKWXpvdcfhuLBevQ5bVUcu/fc= X-Google-Smtp-Source: ABdhPJwb5psvYWCWsRU49QrD70LolMa5euOTE61k2CJmu2I5n6y8HiRBrRK00UvDfeshWnkadhUy2Q== X-Received: by 2002:a17:907:a409:: with SMTP id sg9mr10158763ejc.219.1644824305470; Sun, 13 Feb 2022 23:38:25 -0800 (PST) From: Cosmin Tanislav X-Google-Original-From: Cosmin Tanislav Cc: cosmin.tanislav@analog.com, demonsingur@gmail.com, Lars-Peter Clausen , Michael Hennerich , Rob Herring , linux-iio@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Rob Herring Subject: [PATCH v5 4/5] dt-bindings: iio: accel: add ADXL367 Date: Mon, 14 Feb 2022 09:38:09 +0200 Message-Id: <20220214073810.781016-5-cosmin.tanislav@analog.com> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220214073810.781016-1-cosmin.tanislav@analog.com> References: <20220214073810.781016-1-cosmin.tanislav@analog.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net To: unlisted-recipients:; (no To-header on input) Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZM-MESSAGEID: 1644824316918100004 Content-Type: text/plain; charset="utf-8" The ADXL367 is an ultralow power, 3-axis MEMS accelerometer. The ADXL367 does not alias input signals to achieve ultralow power consumption, it samples the full bandwidth of the sensor at all data rates. Measurement ranges of +-2g, +-4g, and +-8g are available, with a resolution of 0.25mg/LSB on the +-2 g range. In addition to its ultralow power consumption, the ADXL367 has many features to enable true system level power reduction. It includes a deep multimode output FIFO, a built-in micropower temperature sensor, and an internal ADC for synchronous conversion of an additional analog input. Signed-off-by: Cosmin Tanislav Reviewed-by: Rob Herring --- .../bindings/iio/accel/adi,adxl367.yaml | 79 +++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/accel/adi,adxl367= .yaml diff --git a/Documentation/devicetree/bindings/iio/accel/adi,adxl367.yaml b= /Documentation/devicetree/bindings/iio/accel/adi,adxl367.yaml new file mode 100644 index 000000000000..d259e796c1d6 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/accel/adi,adxl367.yaml @@ -0,0 +1,79 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/accel/adi,adxl367.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Analog Devices ADXL367 3-Axis Digital Accelerometer + +maintainers: + - Cosmin Tanislav + +description: | + The ADXL367 is an ultralow power, 3-axis MEMS accelerometer. + + The ADXL367 does not alias input signals by to achieve ultralow power + consumption, it samples the full bandwidth of the sensor at all + data rates. Measurement ranges of +-2g, +-4g, and +-8g are available, + with a resolution of 0.25mg/LSB on the +-2 g range. + + In addition to its ultralow power consumption, the ADXL367 + has many features to enable true system level power reduction. + It includes a deep multimode output FIFO, a built-in micropower + temperature sensor, and an internal ADC for synchronous conversion + of an additional analog input. + https://www.analog.com/en/products/adxl367.html + +properties: + compatible: + enum: + - adi,adxl367 + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + spi-max-frequency: true + + vdd-supply: true + vddio-supply: true + +required: + - compatible + - reg + - interrupts + +additionalProperties: false + +examples: + - | + #include + + i2c { + #address-cells =3D <1>; + #size-cells =3D <0>; + + accelerometer@53 { + compatible =3D "adi,adxl367"; + reg =3D <0x53>; + interrupt-parent =3D <&gpio>; + interrupts =3D <25 IRQ_TYPE_EDGE_RISING>; + }; + }; + - | + #include + + spi { + #address-cells =3D <1>; + #size-cells =3D <0>; + + accelerometer@0 { + compatible =3D "adi,adxl367"; + reg =3D <0>; + spi-max-frequency =3D <1000000>; + interrupt-parent =3D <&gpio>; + interrupts =3D <25 IRQ_TYPE_EDGE_RISING>; + }; + }; --=20 2.35.1 From nobody Tue Apr 23 21:37:18 2024 Delivered-To: importer2@patchew.org Received-SPF: pass (zohomail.com: domain of vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; envelope-from=linux-kernel-owner@vger.kernel.org; helo=vger.kernel.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail(p=none dis=none) header.from=gmail.com Return-Path: Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mx.zohomail.com with SMTP id 1644824320123819.5865731120721; Sun, 13 Feb 2022 23:38:40 -0800 (PST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241499AbiBNHip (ORCPT ); Mon, 14 Feb 2022 02:38:45 -0500 Received: from mxb-00190b01.gslb.pphosted.com ([23.128.96.19]:55760 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229962AbiBNHii (ORCPT ); Mon, 14 Feb 2022 02:38:38 -0500 Received: from mail-ej1-x632.google.com (mail-ej1-x632.google.com [IPv6:2a00:1450:4864:20::632]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B0B2A4F47F; Sun, 13 Feb 2022 23:38:28 -0800 (PST) Received: by mail-ej1-x632.google.com with SMTP id qk11so15166423ejb.2; Sun, 13 Feb 2022 23:38:28 -0800 (PST) Received: from demon-pc.localdomain ([188.24.58.131]) by smtp.gmail.com with ESMTPSA id 9sm2480065ejd.184.2022.02.13.23.38.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 13 Feb 2022 23:38:26 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=TWHUuR4jd+TSQ3flYoauZQ/5tL37aseKm5c2fkKUUbQ=; b=kpRJdoUQEMIeW51jWuiwdWPfqt8LR2wnU/KOrnHT4DfNTbNdwyhf1qe7a+xKxUEPZr NWAaKWnKCPf3LMOezisY06IsiWiBKoW9tUiH8l6TGfwSQ53/C6coL+gqJlTwsZLYfUoz NjDC09QhSajB5BLvjUVDMm1mYxDWF9w569FqjHn5XaQo7dX2/MsA8itdvQMs/mLXuJRK UQJFRiiGF+iuNE8lbxZy0I8ynWazMQsUVLvjJSShhdLDb1AwSXwRlzcEs5Da9n163Yqr EjuNzJWwC1XSc8MtvVH0tdbOaIY+VOEbWZSk0RCxHVe7F2WVWyVpqLFVv6VIGJU9LzvK j+0w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=TWHUuR4jd+TSQ3flYoauZQ/5tL37aseKm5c2fkKUUbQ=; b=vh2CTxoN6CPNvZ+Vcf7VhD0dNsA4vF5N9vpRwHd2tlO8TR+TpSP/F2m52LFsfGX+Ou UE7cvgN7hsHL97AuGPIFv50+Y0XU4kQ9Ehwy155bSwqVqhEQq1Ml42iV+qpMceOEO4F4 c64FwOj+xdjWRtEX4p9XNtc9VqzQYNaYoyCJVT75WVuX08I9tyBOkuu8ythNcoNVokg+ R7QDTcneEug1kic0Swqm58CYQGOhjFBnPKd+dUFpkU8DESG8lYUT0oUvy+B2r0mxIbn5 Xr4q8SIJ7SIBeveT3/IVv4pH4pPJJ+QJTsDHb6zSGTQCTaVvJ6wEcDpAExCfzeO6TyMH W+NA== X-Gm-Message-State: AOAM531UaoftCyUmh3ToOgR0Q3BQ1kPNhV7ecwHBACyJboaESnogxxS/ eqIOzhNPtkJq/NVV1NWKGFE= X-Google-Smtp-Source: ABdhPJyEyqkah2tPwqmms3l7um0QtMTy+SYVoAKvs09fxLdeuhPXogmC0teb9xrWDPA2osRa2f5J4w== X-Received: by 2002:a17:906:d555:: with SMTP id cr21mr6120983ejc.428.1644824306896; Sun, 13 Feb 2022 23:38:26 -0800 (PST) From: Cosmin Tanislav X-Google-Original-From: Cosmin Tanislav Cc: cosmin.tanislav@analog.com, demonsingur@gmail.com, Lars-Peter Clausen , Michael Hennerich , Rob Herring , linux-iio@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v5 5/5] iio: accel: add ADXL367 driver Date: Mon, 14 Feb 2022 09:38:10 +0200 Message-Id: <20220214073810.781016-6-cosmin.tanislav@analog.com> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220214073810.781016-1-cosmin.tanislav@analog.com> References: <20220214073810.781016-1-cosmin.tanislav@analog.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net To: unlisted-recipients:; (no To-header on input) Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZM-MESSAGEID: 1644824321067100001 Content-Type: text/plain; charset="utf-8" The ADXL367 is an ultralow power, 3-axis MEMS accelerometer. The ADXL367 does not alias input signals to achieve ultralow power consumption, it samples the full bandwidth of the sensor at all data rates. Measurement ranges of +-2g, +-4g, and +-8g are available, with a resolution of 0.25mg/LSB on the +-2 g range. In addition to its ultralow power consumption, the ADXL367 has many features to enable true system level power reduction. It includes a deep multimode output FIFO, a built-in micropower temperature sensor, and an internal ADC for synchronous conversion of an additional analog input. Signed-off-by: Cosmin Tanislav --- MAINTAINERS | 8 + drivers/iio/accel/Kconfig | 27 + drivers/iio/accel/Makefile | 3 + drivers/iio/accel/adxl367.c | 1588 +++++++++++++++++++++++++++++++ drivers/iio/accel/adxl367.h | 23 + drivers/iio/accel/adxl367_i2c.c | 90 ++ drivers/iio/accel/adxl367_spi.c | 164 ++++ 7 files changed, 1903 insertions(+) create mode 100644 drivers/iio/accel/adxl367.c create mode 100644 drivers/iio/accel/adxl367.h create mode 100644 drivers/iio/accel/adxl367_i2c.c create mode 100644 drivers/iio/accel/adxl367_spi.c diff --git a/MAINTAINERS b/MAINTAINERS index a2c8699e9e41..3b5393bb6fee 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -606,6 +606,14 @@ F: drivers/iio/accel/adxl355_core.c F: drivers/iio/accel/adxl355_i2c.c F: drivers/iio/accel/adxl355_spi.c =20 +ADXL367 THREE-AXIS DIGITAL ACCELEROMETER DRIVER +M: Cosmin Tanislav +L: linux-iio@vger.kernel.org +S: Supported +W: http://ez.analog.com/community/linux-device-drivers +F: Documentation/devicetree/bindings/iio/accel/adi,adxl367.yaml +F: drivers/iio/accel/adxl367* + ADXL372 THREE-AXIS DIGITAL ACCELEROMETER DRIVER M: Michael Hennerich S: Supported diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig index eb17ca40e08a..eac3f02662ae 100644 --- a/drivers/iio/accel/Kconfig +++ b/drivers/iio/accel/Kconfig @@ -123,6 +123,33 @@ config ADXL355_SPI will be called adxl355_spi and you will also get adxl355_core for the core module. =20 +config ADXL367 + tristate + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER + +config ADXL367_SPI + tristate "Analog Devices ADXL367 3-Axis Accelerometer SPI Driver" + depends on SPI + select ADXL367 + select REGMAP_SPI + help + Say yes here to add support for the Analog Devices ADXL367 triaxial + acceleration sensor. + To compile this driver as a module, choose M here: the + module will be called adxl367_spi. + +config ADXL367_I2C + tristate "Analog Devices ADXL367 3-Axis Accelerometer I2C Driver" + depends on I2C + select ADXL367 + select REGMAP_I2C + help + Say yes here to add support for the Analog Devices ADXL367 triaxial + acceleration sensor. + To compile this driver as a module, choose M here: the + module will be called adxl367_i2c. + config ADXL372 tristate select IIO_BUFFER diff --git a/drivers/iio/accel/Makefile b/drivers/iio/accel/Makefile index d03e2f6bba08..4d8792668838 100644 --- a/drivers/iio/accel/Makefile +++ b/drivers/iio/accel/Makefile @@ -15,6 +15,9 @@ obj-$(CONFIG_ADXL345_SPI) +=3D adxl345_spi.o obj-$(CONFIG_ADXL355) +=3D adxl355_core.o obj-$(CONFIG_ADXL355_I2C) +=3D adxl355_i2c.o obj-$(CONFIG_ADXL355_SPI) +=3D adxl355_spi.o +obj-$(CONFIG_ADXL367) +=3D adxl367.o +obj-$(CONFIG_ADXL367_I2C) +=3D adxl367_i2c.o +obj-$(CONFIG_ADXL367_SPI) +=3D adxl367_spi.o obj-$(CONFIG_ADXL372) +=3D adxl372.o obj-$(CONFIG_ADXL372_I2C) +=3D adxl372_i2c.o obj-$(CONFIG_ADXL372_SPI) +=3D adxl372_spi.o diff --git a/drivers/iio/accel/adxl367.c b/drivers/iio/accel/adxl367.c new file mode 100644 index 000000000000..b452d74b1d4d --- /dev/null +++ b/drivers/iio/accel/adxl367.c @@ -0,0 +1,1588 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2021 Analog Devices, Inc. + * Author: Cosmin Tanislav + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "adxl367.h" + +#define ADXL367_REG_DEVID 0x00 +#define ADXL367_DEVID_AD 0xAD + +#define ADXL367_REG_STATUS 0x0B +#define ADXL367_STATUS_INACT_MASK BIT(5) +#define ADXL367_STATUS_ACT_MASK BIT(4) +#define ADXL367_STATUS_FIFO_FULL_MASK BIT(2) + +#define ADXL367_FIFO_ENT_H_MASK GENMASK(1, 0) + +#define ADXL367_REG_X_DATA_H 0x0E +#define ADXL367_REG_Y_DATA_H 0x10 +#define ADXL367_REG_Z_DATA_H 0x12 +#define ADXL367_REG_TEMP_DATA_H 0x14 +#define ADXL367_REG_EX_ADC_DATA_H 0x16 +#define ADXL367_DATA_MASK GENMASK(15, 2) + +#define ADXL367_TEMP_25C 165 +#define ADXL367_TEMP_PER_C 54 + +#define ADXL367_VOLTAGE_OFFSET 8192 +#define ADXL367_VOLTAGE_MAX_MV 1000 +#define ADXL367_VOLTAGE_MAX_RAW GENMASK(13, 0) + +#define ADXL367_REG_RESET 0x1F +#define ADXL367_RESET_CODE 0x52 + +#define ADXL367_REG_THRESH_ACT_H 0x20 +#define ADXL367_REG_THRESH_INACT_H 0x23 +#define ADXL367_THRESH_MAX GENMASK(12, 0) +#define ADXL367_THRESH_VAL_H_MASK GENMASK(12, 6) +#define ADXL367_THRESH_H_MASK GENMASK(6, 0) +#define ADXL367_THRESH_VAL_L_MASK GENMASK(5, 0) +#define ADXL367_THRESH_L_MASK GENMASK(7, 2) + +#define ADXL367_REG_TIME_ACT 0x22 +#define ADXL367_REG_TIME_INACT_H 0x25 +#define ADXL367_TIME_ACT_MAX GENMASK(7, 0) +#define ADXL367_TIME_INACT_MAX GENMASK(15, 0) +#define ADXL367_TIME_INACT_VAL_H_MASK GENMASK(15, 8) +#define ADXL367_TIME_INACT_H_MASK GENMASK(7, 0) +#define ADXL367_TIME_INACT_VAL_L_MASK GENMASK(7, 0) +#define ADXL367_TIME_INACT_L_MASK GENMASK(7, 0) + +#define ADXL367_REG_ACT_INACT_CTL 0x27 +#define ADXL367_ACT_EN_MASK GENMASK(1, 0) +#define ADXL367_ACT_LINKLOOP_MASK GENMASK(5, 4) + +#define ADXL367_REG_FIFO_CTL 0x28 +#define ADXL367_FIFO_CTL_FORMAT_MASK GENMASK(6, 3) +#define ADXL367_FIFO_CTL_MODE_MASK GENMASK(1, 0) + +#define ADXL367_REG_FIFO_SAMPLES 0x29 +#define ADXL367_FIFO_SIZE 512 +#define ADXL367_FIFO_MAX_WATERMARK 511 + +#define ADXL367_SAMPLES_VAL_H_MASK BIT(8) +#define ADXL367_SAMPLES_H_MASK BIT(2) +#define ADXL367_SAMPLES_VAL_L_MASK GENMASK(7, 0) +#define ADXL367_SAMPLES_L_MASK GENMASK(7, 0) + +#define ADXL367_REG_INT1_MAP 0x2A +#define ADXL367_INT_INACT_MASK BIT(5) +#define ADXL367_INT_ACT_MASK BIT(4) +#define ADXL367_INT_FIFO_WATERMARK_MASK BIT(2) + +#define ADXL367_REG_FILTER_CTL 0x2C +#define ADXL367_FILTER_CTL_RANGE_MASK GENMASK(7, 6) +#define ADXL367_2G_RANGE_1G 4095 +#define ADXL367_2G_RANGE_100MG 409 +#define ADXL367_FILTER_CTL_ODR_MASK GENMASK(2, 0) + +#define ADXL367_REG_POWER_CTL 0x2D +#define ADXL367_POWER_CTL_MODE_MASK GENMASK(1, 0) + +#define ADXL367_REG_ADC_CTL 0x3C +#define ADXL367_REG_TEMP_CTL 0x3D +#define ADXL367_ADC_EN_MASK BIT(0) + +enum adxl367_range { + ADXL367_2G_RANGE, + ADXL367_4G_RANGE, + ADXL367_8G_RANGE, +}; + +enum adxl367_fifo_mode { + ADXL367_FIFO_MODE_DISABLED =3D 0b00, + ADXL367_FIFO_MODE_STREAM =3D 0b10, +}; + +enum adxl367_fifo_format { + ADXL367_FIFO_FORMAT_XYZ, + ADXL367_FIFO_FORMAT_X, + ADXL367_FIFO_FORMAT_Y, + ADXL367_FIFO_FORMAT_Z, + ADXL367_FIFO_FORMAT_XYZT, + ADXL367_FIFO_FORMAT_XT, + ADXL367_FIFO_FORMAT_YT, + ADXL367_FIFO_FORMAT_ZT, + ADXL367_FIFO_FORMAT_XYZA, + ADXL367_FIFO_FORMAT_XA, + ADXL367_FIFO_FORMAT_YA, + ADXL367_FIFO_FORMAT_ZA, +}; + +enum adxl367_op_mode { + ADXL367_OP_STANDBY =3D 0b00, + ADXL367_OP_MEASURE =3D 0b10, +}; + +enum adxl367_act_proc_mode { + ADXL367_LOOPED =3D 0b11, +}; + +enum adxl367_act_en_mode { + ADXL367_ACT_DISABLED =3D 0b00, + ADCL367_ACT_REF_ENABLED =3D 0b11, +}; + +enum adxl367_activity_type { + ADXL367_ACTIVITY, + ADXL367_INACTIVITY, +}; + +enum adxl367_odr { + ADXL367_ODR_12P5HZ, + ADXL367_ODR_25HZ, + ADXL367_ODR_50HZ, + ADXL367_ODR_100HZ, + ADXL367_ODR_200HZ, + ADXL367_ODR_400HZ, +}; + +struct adxl367_state { + const struct adxl367_ops *ops; + void *context; + + struct device *dev; + struct regmap *regmap; + + struct regulator_bulk_data regulators[2]; + + /* + * Synchronize access to members of driver state, and ensure atomicity + * of consecutive regmap operations. + */ + struct mutex lock; + + enum adxl367_odr odr; + enum adxl367_range range; + + unsigned int act_threshold; + unsigned int act_time_ms; + unsigned int inact_threshold; + unsigned int inact_time_ms; + + unsigned int fifo_set_size; + unsigned int fifo_watermark; + + __be16 fifo_buf[ADXL367_FIFO_SIZE] ____cacheline_aligned; + __be16 sample_buf; + u8 act_threshold_buf[2]; + u8 inact_time_buf[2]; + u8 status_buf[3]; +}; + +static const unsigned int adxl367_threshold_h_reg_tbl[] =3D { + [ADXL367_ACTIVITY] =3D ADXL367_REG_THRESH_ACT_H, + [ADXL367_INACTIVITY] =3D ADXL367_REG_THRESH_INACT_H, +}; + +static const unsigned int adxl367_act_en_shift_tbl[] =3D { + [ADXL367_ACTIVITY] =3D 0, + [ADXL367_INACTIVITY] =3D 2, +}; + +static const unsigned int adxl367_act_int_mask_tbl[] =3D { + [ADXL367_ACTIVITY] =3D ADXL367_INT_ACT_MASK, + [ADXL367_INACTIVITY] =3D ADXL367_INT_INACT_MASK, +}; + +static const int adxl367_samp_freq_tbl[][2] =3D { + [ADXL367_ODR_12P5HZ] =3D {12, 500000}, + [ADXL367_ODR_25HZ] =3D {25, 0}, + [ADXL367_ODR_50HZ] =3D {50, 0}, + [ADXL367_ODR_100HZ] =3D {100, 0}, + [ADXL367_ODR_200HZ] =3D {200, 0}, + [ADXL367_ODR_400HZ] =3D {400, 0}, +}; + +/* (g * 2) * 9.80665 * 1000000 / (2^14 - 1) */ +static const int adxl367_range_scale_tbl[][2] =3D { + [ADXL367_2G_RANGE] =3D {0, 2394347}, + [ADXL367_4G_RANGE] =3D {0, 4788695}, + [ADXL367_8G_RANGE] =3D {0, 9577391}, +}; + +static const int adxl367_range_scale_factor_tbl[] =3D { + [ADXL367_2G_RANGE] =3D 1, + [ADXL367_4G_RANGE] =3D 2, + [ADXL367_8G_RANGE] =3D 4, +}; + +enum { + ADXL367_X_CHANNEL_INDEX, + ADXL367_Y_CHANNEL_INDEX, + ADXL367_Z_CHANNEL_INDEX, + ADXL367_TEMP_CHANNEL_INDEX, + ADXL367_EX_ADC_CHANNEL_INDEX +}; + +#define ADXL367_X_CHANNEL_MASK BIT(ADXL367_X_CHANNEL_INDEX) +#define ADXL367_Y_CHANNEL_MASK BIT(ADXL367_Y_CHANNEL_INDEX) +#define ADXL367_Z_CHANNEL_MASK BIT(ADXL367_Z_CHANNEL_INDEX) +#define ADXL367_TEMP_CHANNEL_MASK BIT(ADXL367_TEMP_CHANNEL_INDEX) +#define ADXL367_EX_ADC_CHANNEL_MASK BIT(ADXL367_EX_ADC_CHANNEL_INDEX) + +static const enum adxl367_fifo_format adxl367_fifo_formats[] =3D { + ADXL367_FIFO_FORMAT_X, + ADXL367_FIFO_FORMAT_Y, + ADXL367_FIFO_FORMAT_Z, + ADXL367_FIFO_FORMAT_XT, + ADXL367_FIFO_FORMAT_YT, + ADXL367_FIFO_FORMAT_ZT, + ADXL367_FIFO_FORMAT_XA, + ADXL367_FIFO_FORMAT_YA, + ADXL367_FIFO_FORMAT_ZA, + ADXL367_FIFO_FORMAT_XYZ, + ADXL367_FIFO_FORMAT_XYZT, + ADXL367_FIFO_FORMAT_XYZA, +}; + +static const unsigned long adxl367_channel_masks[] =3D { + ADXL367_X_CHANNEL_MASK, + ADXL367_Y_CHANNEL_MASK, + ADXL367_Z_CHANNEL_MASK, + ADXL367_X_CHANNEL_MASK | ADXL367_TEMP_CHANNEL_MASK, + ADXL367_Y_CHANNEL_MASK | ADXL367_TEMP_CHANNEL_MASK, + ADXL367_Z_CHANNEL_MASK | ADXL367_TEMP_CHANNEL_MASK, + ADXL367_X_CHANNEL_MASK | ADXL367_EX_ADC_CHANNEL_MASK, + ADXL367_Y_CHANNEL_MASK | ADXL367_EX_ADC_CHANNEL_MASK, + ADXL367_Z_CHANNEL_MASK | ADXL367_EX_ADC_CHANNEL_MASK, + ADXL367_X_CHANNEL_MASK | ADXL367_Y_CHANNEL_MASK | ADXL367_Z_CHANNEL_MASK, + ADXL367_X_CHANNEL_MASK | ADXL367_Y_CHANNEL_MASK | ADXL367_Z_CHANNEL_MASK | + ADXL367_TEMP_CHANNEL_MASK, + ADXL367_X_CHANNEL_MASK | ADXL367_Y_CHANNEL_MASK | ADXL367_Z_CHANNEL_MASK | + ADXL367_EX_ADC_CHANNEL_MASK, + 0, +}; + +static int adxl367_set_measure_en(struct adxl367_state *st, bool en) +{ + enum adxl367_op_mode op_mode =3D en ? ADXL367_OP_MEASURE + : ADXL367_OP_STANDBY; + int ret; + + ret =3D regmap_update_bits(st->regmap, ADXL367_REG_POWER_CTL, + ADXL367_POWER_CTL_MODE_MASK, + FIELD_PREP(ADXL367_POWER_CTL_MODE_MASK, + op_mode)); + if (ret) + return ret; + + /* + * Wait for acceleration output to settle after entering + * measure mode. + */ + if (en) + msleep(100); + + return 0; +} + +static void adxl367_scale_act_thresholds(struct adxl367_state *st, + enum adxl367_range old_range, + enum adxl367_range new_range) +{ + st->act_threshold =3D st->act_threshold + * adxl367_range_scale_factor_tbl[old_range] + / adxl367_range_scale_factor_tbl[new_range]; + st->inact_threshold =3D st->inact_threshold + * adxl367_range_scale_factor_tbl[old_range] + / adxl367_range_scale_factor_tbl[new_range]; +} + +static int _adxl367_set_act_threshold(struct adxl367_state *st, + enum adxl367_activity_type act, + unsigned int threshold) +{ + u8 reg =3D adxl367_threshold_h_reg_tbl[act]; + int ret; + + if (threshold > ADXL367_THRESH_MAX) + return -EINVAL; + + st->act_threshold_buf[0] =3D FIELD_PREP(ADXL367_THRESH_H_MASK, + FIELD_GET(ADXL367_THRESH_VAL_H_MASK, + threshold)); + st->act_threshold_buf[1] =3D FIELD_PREP(ADXL367_THRESH_L_MASK, + FIELD_GET(ADXL367_THRESH_VAL_L_MASK, + threshold)); + + ret =3D regmap_bulk_write(st->regmap, reg, st->act_threshold_buf, + sizeof(st->act_threshold_buf)); + if (ret) + return ret; + + if (act =3D=3D ADXL367_ACTIVITY) + st->act_threshold =3D threshold; + else + st->inact_threshold =3D threshold; + + return 0; +} + +static int adxl367_set_act_threshold(struct adxl367_state *st, + enum adxl367_activity_type act, + unsigned int threshold) +{ + int ret; + + mutex_lock(&st->lock); + + ret =3D adxl367_set_measure_en(st, false); + if (ret) + goto out; + + ret =3D _adxl367_set_act_threshold(st, act, threshold); + if (ret) + goto out; + + ret =3D adxl367_set_measure_en(st, true); + +out: + mutex_unlock(&st->lock); + + return ret; +} + +static int adxl367_set_act_proc_mode(struct adxl367_state *st, + enum adxl367_act_proc_mode mode) +{ + return regmap_update_bits(st->regmap, ADXL367_REG_ACT_INACT_CTL, + ADXL367_ACT_LINKLOOP_MASK, + FIELD_PREP(ADXL367_ACT_LINKLOOP_MASK, + mode)); +} + +static int adxl367_set_act_interrupt_en(struct adxl367_state *st, + enum adxl367_activity_type act, + bool en) +{ + unsigned int mask =3D adxl367_act_int_mask_tbl[act]; + + return regmap_update_bits(st->regmap, ADXL367_REG_INT1_MAP, + mask, en ? mask : 0); +} + +static int adxl367_get_act_interrupt_en(struct adxl367_state *st, + enum adxl367_activity_type act, + bool *en) +{ + unsigned int mask =3D adxl367_act_int_mask_tbl[act]; + unsigned int val; + int ret; + + ret =3D regmap_read(st->regmap, ADXL367_REG_INT1_MAP, &val); + if (ret) + return ret; + + *en =3D !!(val & mask); + + return 0; +} + +static int adxl367_set_act_en(struct adxl367_state *st, + enum adxl367_activity_type act, + enum adxl367_act_en_mode en) +{ + unsigned int ctl_shift =3D adxl367_act_en_shift_tbl[act]; + + return regmap_update_bits(st->regmap, ADXL367_REG_ACT_INACT_CTL, + ADXL367_ACT_EN_MASK << ctl_shift, + en << ctl_shift); +} + +static int adxl367_set_fifo_watermark_interrupt_en(struct adxl367_state *s= t, + bool en) +{ + return regmap_update_bits(st->regmap, ADXL367_REG_INT1_MAP, + ADXL367_INT_FIFO_WATERMARK_MASK, + en ? ADXL367_INT_FIFO_WATERMARK_MASK : 0); +} + +static int adxl367_get_fifo_mode(struct adxl367_state *st, + enum adxl367_fifo_mode *fifo_mode) +{ + unsigned int val; + int ret; + + ret =3D regmap_read(st->regmap, ADXL367_REG_FIFO_CTL, &val); + if (ret) + return ret; + + *fifo_mode =3D FIELD_GET(ADXL367_FIFO_CTL_MODE_MASK, val); + + return 0; +} + +static int adxl367_set_fifo_mode(struct adxl367_state *st, + enum adxl367_fifo_mode fifo_mode) +{ + return regmap_update_bits(st->regmap, ADXL367_REG_FIFO_CTL, + ADXL367_FIFO_CTL_MODE_MASK, + FIELD_PREP(ADXL367_FIFO_CTL_MODE_MASK, + fifo_mode)); +} + +static int adxl367_set_fifo_format(struct adxl367_state *st, + enum adxl367_fifo_format fifo_format) +{ + return regmap_update_bits(st->regmap, ADXL367_REG_FIFO_CTL, + ADXL367_FIFO_CTL_FORMAT_MASK, + FIELD_PREP(ADXL367_FIFO_CTL_FORMAT_MASK, + fifo_format)); +} + +static int adxl367_set_fifo_samples(struct adxl367_state *st, + unsigned int fifo_watermark, + unsigned int fifo_set_size) +{ + unsigned int fifo_samples =3D fifo_watermark * fifo_set_size; + unsigned int fifo_samples_h, fifo_samples_l; + int ret; + + if (fifo_samples > ADXL367_FIFO_MAX_WATERMARK) + fifo_samples =3D ADXL367_FIFO_MAX_WATERMARK; + + if (fifo_set_size =3D=3D 0) + return 0; + + fifo_samples /=3D fifo_set_size; + + fifo_samples_h =3D FIELD_PREP(ADXL367_SAMPLES_H_MASK, + FIELD_GET(ADXL367_SAMPLES_VAL_H_MASK, + fifo_samples)); + fifo_samples_l =3D FIELD_PREP(ADXL367_SAMPLES_L_MASK, + FIELD_GET(ADXL367_SAMPLES_VAL_L_MASK, + fifo_samples)); + + ret =3D regmap_update_bits(st->regmap, ADXL367_REG_FIFO_CTL, + ADXL367_SAMPLES_H_MASK, fifo_samples_h); + if (ret) + return ret; + + return regmap_update_bits(st->regmap, ADXL367_REG_FIFO_SAMPLES, + ADXL367_SAMPLES_L_MASK, fifo_samples_l); +} + +static int adxl367_set_fifo_set_size(struct adxl367_state *st, + unsigned int fifo_set_size) +{ + int ret; + + ret =3D adxl367_set_fifo_samples(st, st->fifo_watermark, fifo_set_size); + if (ret) + return ret; + + st->fifo_set_size =3D fifo_set_size; + + return 0; +} + +static int adxl367_set_fifo_watermark(struct adxl367_state *st, + unsigned int fifo_watermark) +{ + int ret; + + ret =3D adxl367_set_fifo_samples(st, fifo_watermark, st->fifo_set_size); + if (ret) + return ret; + + st->fifo_watermark =3D fifo_watermark; + + return 0; +} + +static int adxl367_set_range(struct iio_dev *indio_dev, + enum adxl367_range range) +{ + struct adxl367_state *st =3D iio_priv(indio_dev); + int ret; + + ret =3D iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; + + mutex_lock(&st->lock); + + ret =3D adxl367_set_measure_en(st, false); + if (ret) + goto out; + + ret =3D regmap_update_bits(st->regmap, ADXL367_REG_FILTER_CTL, + ADXL367_FILTER_CTL_RANGE_MASK, + FIELD_PREP(ADXL367_FILTER_CTL_RANGE_MASK, + range)); + if (ret) + goto out; + + adxl367_scale_act_thresholds(st, st->range, range); + + /* Activity thresholds depend on range */ + ret =3D _adxl367_set_act_threshold(st, ADXL367_ACTIVITY, + st->act_threshold); + if (ret) + goto out; + + ret =3D _adxl367_set_act_threshold(st, ADXL367_INACTIVITY, + st->inact_threshold); + if (ret) + goto out; + + ret =3D adxl367_set_measure_en(st, true); + if (ret) + goto out; + + st->range =3D range; + +out: + mutex_unlock(&st->lock); + + iio_device_release_direct_mode(indio_dev); + + return ret; +} + +static int adxl367_time_ms_to_samples(struct adxl367_state *st, unsigned i= nt ms) +{ + int freq_hz =3D adxl367_samp_freq_tbl[st->odr][0]; + int freq_microhz =3D adxl367_samp_freq_tbl[st->odr][1]; + /* Scale to decihertz to prevent precision loss in 12.5Hz case. */ + int freq_dhz =3D freq_hz * 10 + freq_microhz / 100000; + + return DIV_ROUND_CLOSEST(ms * freq_dhz, 10000); +} + +static int _adxl367_set_act_time_ms(struct adxl367_state *st, unsigned int= ms) +{ + unsigned int val =3D adxl367_time_ms_to_samples(st, ms); + int ret; + + if (val > ADXL367_TIME_ACT_MAX) + val =3D ADXL367_TIME_ACT_MAX; + + ret =3D regmap_write(st->regmap, ADXL367_REG_TIME_ACT, val); + if (ret) + return ret; + + st->act_time_ms =3D ms; + + return 0; +} + +static int _adxl367_set_inact_time_ms(struct adxl367_state *st, unsigned i= nt ms) +{ + unsigned int val =3D adxl367_time_ms_to_samples(st, ms); + int ret; + + if (val > ADXL367_TIME_INACT_MAX) + val =3D ADXL367_TIME_INACT_MAX; + + st->inact_time_buf[0] =3D FIELD_PREP(ADXL367_TIME_INACT_H_MASK, + FIELD_GET(ADXL367_TIME_INACT_VAL_H_MASK, + val)); + st->inact_time_buf[1] =3D FIELD_PREP(ADXL367_TIME_INACT_L_MASK, + FIELD_GET(ADXL367_TIME_INACT_VAL_L_MASK, + val)); + + ret =3D regmap_bulk_write(st->regmap, ADXL367_REG_TIME_INACT_H, + st->inact_time_buf, sizeof(st->inact_time_buf)); + if (ret) + return ret; + + st->inact_time_ms =3D ms; + + return 0; +} + +static int adxl367_set_act_time_ms(struct adxl367_state *st, + enum adxl367_activity_type act, + unsigned int ms) +{ + int ret; + + mutex_lock(&st->lock); + + ret =3D adxl367_set_measure_en(st, false); + if (ret) + goto out; + + if (act =3D=3D ADXL367_ACTIVITY) + ret =3D _adxl367_set_act_time_ms(st, ms); + else + ret =3D _adxl367_set_inact_time_ms(st, ms); + + if (ret) + goto out; + + ret =3D adxl367_set_measure_en(st, true); + +out: + mutex_unlock(&st->lock); + + return ret; +} + +static int _adxl367_set_odr(struct adxl367_state *st, enum adxl367_odr odr) +{ + int ret; + + ret =3D regmap_update_bits(st->regmap, ADXL367_REG_FILTER_CTL, + ADXL367_FILTER_CTL_ODR_MASK, + FIELD_PREP(ADXL367_FILTER_CTL_ODR_MASK, + odr)); + if (ret) + return ret; + + /* Activity timers depend on ODR */ + ret =3D _adxl367_set_act_time_ms(st, st->act_time_ms); + if (ret) + return ret; + + ret =3D _adxl367_set_inact_time_ms(st, st->inact_time_ms); + if (ret) + return ret; + + st->odr =3D odr; + + return 0; +} + +static int adxl367_set_odr(struct iio_dev *indio_dev, enum adxl367_odr odr) +{ + struct adxl367_state *st =3D iio_priv(indio_dev); + int ret; + + ret =3D iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; + + mutex_lock(&st->lock); + + ret =3D adxl367_set_measure_en(st, false); + if (ret) + goto out; + + ret =3D _adxl367_set_odr(st, odr); + if (ret) + goto out; + + ret =3D adxl367_set_measure_en(st, true); + +out: + mutex_unlock(&st->lock); + + iio_device_release_direct_mode(indio_dev); + + return ret; +} + +static int adxl367_set_temp_adc_en(struct adxl367_state *st, unsigned int = reg, + bool en) +{ + return regmap_update_bits(st->regmap, reg, ADXL367_ADC_EN_MASK, + en ? ADXL367_ADC_EN_MASK : 0); +} + +static int adxl367_set_temp_adc_reg_en(struct adxl367_state *st, + unsigned int reg, bool en) +{ + int ret; + + switch (reg) { + case ADXL367_REG_TEMP_DATA_H: + ret =3D adxl367_set_temp_adc_en(st, ADXL367_REG_TEMP_CTL, en); + break; + case ADXL367_REG_EX_ADC_DATA_H: + ret =3D adxl367_set_temp_adc_en(st, ADXL367_REG_ADC_CTL, en); + break; + default: + return 0; + } + + if (ret) + return ret; + + if (en) + msleep(100); + + return 0; +} + +static int adxl367_set_temp_adc_mask_en(struct adxl367_state *st, + const unsigned long *active_scan_mask, + bool en) +{ + if (*active_scan_mask & ADXL367_TEMP_CHANNEL_MASK) + return adxl367_set_temp_adc_en(st, ADXL367_REG_TEMP_CTL, en); + else if (*active_scan_mask & ADXL367_EX_ADC_CHANNEL_MASK) + return adxl367_set_temp_adc_en(st, ADXL367_REG_ADC_CTL, en); + + return 0; +} + +static int adxl367_find_odr(struct adxl367_state *st, int val, int val2, + enum adxl367_odr *odr) +{ + size_t size =3D ARRAY_SIZE(adxl367_samp_freq_tbl); + int i; + + for (i =3D 0; i < size; i++) + if (val =3D=3D adxl367_samp_freq_tbl[i][0] && + val2 =3D=3D adxl367_samp_freq_tbl[i][1]) + break; + + if (i =3D=3D size) + return -EINVAL; + + *odr =3D i; + + return 0; +} + +static int adxl367_find_range(struct adxl367_state *st, int val, int val2, + enum adxl367_range *range) +{ + size_t size =3D ARRAY_SIZE(adxl367_range_scale_tbl); + int i; + + for (i =3D 0; i < size; i++) + if (val =3D=3D adxl367_range_scale_tbl[i][0] && + val2 =3D=3D adxl367_range_scale_tbl[i][1]) + break; + + if (i =3D=3D size) + return -EINVAL; + + *range =3D i; + + return 0; +} + +static int adxl367_read_sample(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val) +{ + struct adxl367_state *st =3D iio_priv(indio_dev); + u16 sample; + int ret; + + ret =3D iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; + + mutex_lock(&st->lock); + + ret =3D adxl367_set_temp_adc_reg_en(st, chan->address, true); + if (ret) + goto out; + + ret =3D regmap_bulk_read(st->regmap, chan->address, &st->sample_buf, + sizeof(st->sample_buf)); + if (ret) + goto out; + + sample =3D FIELD_GET(ADXL367_DATA_MASK, be16_to_cpu(st->sample_buf)); + *val =3D sign_extend32(sample, chan->scan_type.realbits - 1); + + ret =3D adxl367_set_temp_adc_reg_en(st, chan->address, false); + +out: + mutex_unlock(&st->lock); + + iio_device_release_direct_mode(indio_dev); + + return ret ?: IIO_VAL_INT; +} + +static int adxl367_get_status(struct adxl367_state *st, u8 *status, + u16 *fifo_entries) +{ + int ret; + + /* Read STATUS, FIFO_ENT_L and FIFO_ENT_H */ + ret =3D regmap_bulk_read(st->regmap, ADXL367_REG_STATUS, + st->status_buf, sizeof(st->status_buf)); + if (ret) + return ret; + + st->status_buf[2] &=3D ADXL367_FIFO_ENT_H_MASK; + + *status =3D st->status_buf[0]; + *fifo_entries =3D get_unaligned_le16(&st->status_buf[1]); + + return 0; +} + +static bool adxl367_push_event(struct iio_dev *indio_dev, u8 status) +{ + unsigned int ev_dir; + + if (FIELD_GET(ADXL367_STATUS_ACT_MASK, status)) + ev_dir =3D IIO_EV_DIR_RISING; + else if (FIELD_GET(ADXL367_STATUS_INACT_MASK, status)) + ev_dir =3D IIO_EV_DIR_FALLING; + else + return false; + + iio_push_event(indio_dev, + IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, IIO_MOD_X_OR_Y_OR_Z, + IIO_EV_TYPE_THRESH, ev_dir), + iio_get_time_ns(indio_dev)); + + return true; +} + +static bool adxl367_push_fifo_data(struct iio_dev *indio_dev, u8 status, + u16 fifo_entries) +{ + struct adxl367_state *st =3D iio_priv(indio_dev); + int ret; + int i; + + if (!FIELD_GET(ADXL367_STATUS_FIFO_FULL_MASK, status)) + return false; + + fifo_entries -=3D fifo_entries % st->fifo_set_size; + + ret =3D st->ops->read_fifo(st->context, st->fifo_buf, fifo_entries); + if (ret) { + dev_err(st->dev, "Failed to read FIFO: %d\n", ret); + return true; + } + + for (i =3D 0; i < fifo_entries; i +=3D st->fifo_set_size) + iio_push_to_buffers(indio_dev, &st->fifo_buf[i]); + + return true; +} + +static irqreturn_t adxl367_irq_handler(int irq, void *private) +{ + struct iio_dev *indio_dev =3D private; + struct adxl367_state *st =3D iio_priv(indio_dev); + u16 fifo_entries; + bool handled; + u8 status; + int ret; + + ret =3D adxl367_get_status(st, &status, &fifo_entries); + if (ret) + return IRQ_NONE; + + handled |=3D adxl367_push_event(indio_dev, status); + handled |=3D adxl367_push_fifo_data(indio_dev, status, fifo_entries); + + return handled ? IRQ_HANDLED : IRQ_NONE; +} + +static int adxl367_reg_access(struct iio_dev *indio_dev, + unsigned int reg, + unsigned int writeval, + unsigned int *readval) +{ + struct adxl367_state *st =3D iio_priv(indio_dev); + + if (readval) + return regmap_read(st->regmap, reg, readval); + else + return regmap_write(st->regmap, reg, writeval); +} + +static int adxl367_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long info) +{ + struct adxl367_state *st =3D iio_priv(indio_dev); + + switch (info) { + case IIO_CHAN_INFO_RAW: + return adxl367_read_sample(indio_dev, chan, val); + case IIO_CHAN_INFO_SCALE: + switch (chan->type) { + case IIO_ACCEL: + mutex_lock(&st->lock); + *val =3D adxl367_range_scale_tbl[st->range][0]; + *val2 =3D adxl367_range_scale_tbl[st->range][1]; + mutex_unlock(&st->lock); + return IIO_VAL_INT_PLUS_NANO; + case IIO_TEMP: + *val =3D 1000; + *val2 =3D ADXL367_TEMP_PER_C; + return IIO_VAL_FRACTIONAL; + case IIO_VOLTAGE: + *val =3D ADXL367_VOLTAGE_MAX_MV; + *val2 =3D ADXL367_VOLTAGE_MAX_RAW; + return IIO_VAL_FRACTIONAL; + default: + return -EINVAL; + } + case IIO_CHAN_INFO_OFFSET: + switch (chan->type) { + case IIO_TEMP: + *val =3D 25 * ADXL367_TEMP_PER_C - ADXL367_TEMP_25C; + return IIO_VAL_INT; + case IIO_VOLTAGE: + *val =3D ADXL367_VOLTAGE_OFFSET; + return IIO_VAL_INT; + default: + return -EINVAL; + } + case IIO_CHAN_INFO_SAMP_FREQ: + mutex_lock(&st->lock); + *val =3D adxl367_samp_freq_tbl[st->odr][0]; + *val2 =3D adxl367_samp_freq_tbl[st->odr][1]; + mutex_unlock(&st->lock); + return IIO_VAL_INT_PLUS_MICRO; + default: + return -EINVAL; + } +} + +static int adxl367_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long info) +{ + struct adxl367_state *st =3D iio_priv(indio_dev); + int ret; + + switch (info) { + case IIO_CHAN_INFO_SAMP_FREQ: { + enum adxl367_odr odr; + + ret =3D adxl367_find_odr(st, val, val2, &odr); + if (ret) + return ret; + + return adxl367_set_odr(indio_dev, odr); + } + case IIO_CHAN_INFO_SCALE: { + enum adxl367_range range; + + ret =3D adxl367_find_range(st, val, val2, &range); + if (ret) + return ret; + + return adxl367_set_range(indio_dev, range); + } + default: + return -EINVAL; + } +} + +static int adxl367_write_raw_get_fmt(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + long info) +{ + switch (info) { + case IIO_CHAN_INFO_SCALE: + if (chan->type !=3D IIO_ACCEL) + return -EINVAL; + + return IIO_VAL_INT_PLUS_NANO; + default: + return IIO_VAL_INT_PLUS_MICRO; + } +} + +static int adxl367_read_avail(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + const int **vals, int *type, int *length, + long info) +{ + switch (info) { + case IIO_CHAN_INFO_SCALE: + if (chan->type !=3D IIO_ACCEL) + return -EINVAL; + + *vals =3D (int *)adxl367_range_scale_tbl; + *type =3D IIO_VAL_INT_PLUS_NANO; + *length =3D ARRAY_SIZE(adxl367_range_scale_tbl) * 2; + return IIO_AVAIL_LIST; + case IIO_CHAN_INFO_SAMP_FREQ: + *vals =3D (int *)adxl367_samp_freq_tbl; + *type =3D IIO_VAL_INT_PLUS_MICRO; + *length =3D ARRAY_SIZE(adxl367_samp_freq_tbl) * 2; + return IIO_AVAIL_LIST; + default: + return -EINVAL; + } +} + +static int adxl367_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 adxl367_state *st =3D iio_priv(indio_dev); + + switch (info) { + case IIO_EV_INFO_VALUE: { + switch (dir) { + case IIO_EV_DIR_RISING: + mutex_lock(&st->lock); + *val =3D st->act_threshold; + mutex_unlock(&st->lock); + return IIO_VAL_INT; + case IIO_EV_DIR_FALLING: + mutex_lock(&st->lock); + *val =3D st->inact_threshold; + mutex_unlock(&st->lock); + return IIO_VAL_INT; + default: + return -EINVAL; + } + } + case IIO_EV_INFO_PERIOD: + switch (dir) { + case IIO_EV_DIR_RISING: + mutex_lock(&st->lock); + *val =3D st->act_time_ms; + mutex_unlock(&st->lock); + *val2 =3D 1000; + return IIO_VAL_FRACTIONAL; + case IIO_EV_DIR_FALLING: + mutex_lock(&st->lock); + *val =3D st->inact_time_ms; + mutex_unlock(&st->lock); + *val2 =3D 1000; + return IIO_VAL_FRACTIONAL; + default: + return -EINVAL; + } + default: + return -EINVAL; + } +} + +static int adxl367_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 adxl367_state *st =3D iio_priv(indio_dev); + + switch (info) { + case IIO_EV_INFO_VALUE: + if (val < 0) + return -EINVAL; + + switch (dir) { + case IIO_EV_DIR_RISING: + return adxl367_set_act_threshold(st, ADXL367_ACTIVITY, val); + case IIO_EV_DIR_FALLING: + return adxl367_set_act_threshold(st, ADXL367_INACTIVITY, val); + default: + return -EINVAL; + } + case IIO_EV_INFO_PERIOD: + if (val < 0) + return -EINVAL; + + val =3D val * 1000 + DIV_ROUND_UP(val2, 1000); + switch (dir) { + case IIO_EV_DIR_RISING: + return adxl367_set_act_time_ms(st, ADXL367_ACTIVITY, val); + case IIO_EV_DIR_FALLING: + return adxl367_set_act_time_ms(st, ADXL367_INACTIVITY, val); + default: + return -EINVAL; + } + default: + return -EINVAL; + } +} + +static int adxl367_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 adxl367_state *st =3D iio_priv(indio_dev); + bool en; + int ret; + + switch (dir) { + case IIO_EV_DIR_RISING: + ret =3D adxl367_get_act_interrupt_en(st, ADXL367_ACTIVITY, &en); + return ret ?: en; + case IIO_EV_DIR_FALLING: + ret =3D adxl367_get_act_interrupt_en(st, ADXL367_INACTIVITY, &en); + return ret ?: en; + default: + return -EINVAL; + } +} + +static int adxl367_write_event_config(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + int state) +{ + struct adxl367_state *st =3D iio_priv(indio_dev); + enum adxl367_activity_type act; + int ret; + + switch (dir) { + case IIO_EV_DIR_RISING: + act =3D ADXL367_ACTIVITY; + break; + case IIO_EV_DIR_FALLING: + act =3D ADXL367_INACTIVITY; + break; + default: + return -EINVAL; + } + + ret =3D iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; + + mutex_lock(&st->lock); + + ret =3D adxl367_set_measure_en(st, false); + if (ret) + goto out; + + ret =3D adxl367_set_act_interrupt_en(st, act, state); + if (ret) + goto out; + + ret =3D adxl367_set_act_en(st, act, state ? ADCL367_ACT_REF_ENABLED + : ADXL367_ACT_DISABLED); + if (ret) + goto out; + + ret =3D adxl367_set_measure_en(st, true); + +out: + mutex_unlock(&st->lock); + + iio_device_release_direct_mode(indio_dev); + + return ret; +} + +static ssize_t adxl367_get_fifo_enabled(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct adxl367_state *st =3D iio_priv(dev_to_iio_dev(dev)); + enum adxl367_fifo_mode fifo_mode; + int ret; + + ret =3D adxl367_get_fifo_mode(st, &fifo_mode); + if (ret) + return ret; + + return sysfs_emit(buf, "%d\n", fifo_mode !=3D ADXL367_FIFO_MODE_DISABLED); +} + +static ssize_t adxl367_get_fifo_watermark(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct adxl367_state *st =3D iio_priv(dev_to_iio_dev(dev)); + unsigned int fifo_watermark; + + mutex_lock(&st->lock); + fifo_watermark =3D st->fifo_watermark; + mutex_unlock(&st->lock); + + return sysfs_emit(buf, "%d\n", fifo_watermark); +} + +static IIO_CONST_ATTR(hwfifo_watermark_min, "1"); +static IIO_CONST_ATTR(hwfifo_watermark_max, + __stringify(ADXL367_FIFO_MAX_WATERMARK)); +static IIO_DEVICE_ATTR(hwfifo_watermark, 0444, + adxl367_get_fifo_watermark, NULL, 0); +static IIO_DEVICE_ATTR(hwfifo_enabled, 0444, + adxl367_get_fifo_enabled, NULL, 0); + +static const struct attribute *adxl367_fifo_attributes[] =3D { + &iio_const_attr_hwfifo_watermark_min.dev_attr.attr, + &iio_const_attr_hwfifo_watermark_max.dev_attr.attr, + &iio_dev_attr_hwfifo_watermark.dev_attr.attr, + &iio_dev_attr_hwfifo_enabled.dev_attr.attr, + NULL, +}; + +static int adxl367_set_watermark(struct iio_dev *indio_dev, unsigned int v= al) +{ + struct adxl367_state *st =3D iio_priv(indio_dev); + int ret; + + if (val > ADXL367_FIFO_MAX_WATERMARK) + return -EINVAL; + + mutex_lock(&st->lock); + + ret =3D adxl367_set_measure_en(st, false); + if (ret) + goto out; + + ret =3D adxl367_set_fifo_watermark(st, val); + if (ret) + goto out; + + ret =3D adxl367_set_measure_en(st, true); + +out: + mutex_unlock(&st->lock); + + return ret; +} + +static bool adxl367_find_mask_fifo_format(const unsigned long *scan_mask, + enum adxl367_fifo_format *fifo_format) +{ + size_t size =3D ARRAY_SIZE(adxl367_fifo_formats); + int i; + + for (i =3D 0; i < size; i++) + if (*scan_mask =3D=3D adxl367_channel_masks[i]) + break; + + if (i =3D=3D size) + return false; + + *fifo_format =3D adxl367_fifo_formats[i]; + + return true; +} + +static int adxl367_update_scan_mode(struct iio_dev *indio_dev, + const unsigned long *active_scan_mask) +{ + struct adxl367_state *st =3D iio_priv(indio_dev); + enum adxl367_fifo_format fifo_format; + unsigned int fifo_set_size; + int ret; + + if (!adxl367_find_mask_fifo_format(active_scan_mask, &fifo_format)) + return -EINVAL; + + fifo_set_size =3D bitmap_weight(active_scan_mask, indio_dev->masklength); + + mutex_lock(&st->lock); + + ret =3D adxl367_set_measure_en(st, false); + if (ret) + goto out; + + ret =3D adxl367_set_fifo_format(st, fifo_format); + if (ret) + goto out; + + ret =3D adxl367_set_fifo_set_size(st, fifo_set_size); + if (ret) + goto out; + + ret =3D adxl367_set_measure_en(st, true); + +out: + mutex_unlock(&st->lock); + + return ret; +} + +static int adxl367_buffer_postenable(struct iio_dev *indio_dev) +{ + struct adxl367_state *st =3D iio_priv(indio_dev); + int ret; + + mutex_lock(&st->lock); + + ret =3D adxl367_set_temp_adc_mask_en(st, indio_dev->active_scan_mask, + true); + if (ret) + goto out; + + ret =3D adxl367_set_measure_en(st, false); + if (ret) + goto out; + + ret =3D adxl367_set_fifo_watermark_interrupt_en(st, true); + if (ret) + goto out; + + ret =3D adxl367_set_fifo_mode(st, ADXL367_FIFO_MODE_STREAM); + if (ret) + goto out; + + ret =3D adxl367_set_measure_en(st, true); + +out: + mutex_unlock(&st->lock); + + return ret; +} + +static int adxl367_buffer_predisable(struct iio_dev *indio_dev) +{ + struct adxl367_state *st =3D iio_priv(indio_dev); + int ret; + + mutex_lock(&st->lock); + + ret =3D adxl367_set_measure_en(st, false); + if (ret) + goto out; + + ret =3D adxl367_set_fifo_mode(st, ADXL367_FIFO_MODE_DISABLED); + if (ret) + goto out; + + ret =3D adxl367_set_fifo_watermark_interrupt_en(st, false); + if (ret) + goto out; + + ret =3D adxl367_set_measure_en(st, true); + if (ret) + return ret; + + ret =3D adxl367_set_temp_adc_mask_en(st, indio_dev->active_scan_mask, + false); + +out: + mutex_unlock(&st->lock); + + return ret; +} + +static const struct iio_buffer_setup_ops adxl367_buffer_ops =3D { + .postenable =3D adxl367_buffer_postenable, + .predisable =3D adxl367_buffer_predisable, +}; + +static const struct iio_info adxl367_info =3D { + .read_raw =3D adxl367_read_raw, + .write_raw =3D adxl367_write_raw, + .write_raw_get_fmt =3D adxl367_write_raw_get_fmt, + .read_avail =3D adxl367_read_avail, + .read_event_config =3D adxl367_read_event_config, + .write_event_config =3D adxl367_write_event_config, + .read_event_value =3D adxl367_read_event_value, + .write_event_value =3D adxl367_write_event_value, + .debugfs_reg_access =3D adxl367_reg_access, + .hwfifo_set_watermark =3D adxl367_set_watermark, + .update_scan_mode =3D adxl367_update_scan_mode, +}; + +static const struct iio_event_spec adxl367_events[] =3D { + { + .type =3D IIO_EV_TYPE_MAG_REFERENCED, + .dir =3D IIO_EV_DIR_RISING, + .mask_shared_by_type =3D BIT(IIO_EV_INFO_ENABLE) | + BIT(IIO_EV_INFO_PERIOD) | + BIT(IIO_EV_INFO_VALUE), + }, + { + .type =3D IIO_EV_TYPE_MAG_REFERENCED, + .dir =3D IIO_EV_DIR_FALLING, + .mask_shared_by_type =3D BIT(IIO_EV_INFO_ENABLE) | + BIT(IIO_EV_INFO_PERIOD) | + BIT(IIO_EV_INFO_VALUE), + }, +}; + +#define ADXL367_ACCEL_CHANNEL(index, reg, axis) { \ + .type =3D IIO_ACCEL, \ + .address =3D (reg), \ + .modified =3D 1, \ + .channel2 =3D IIO_MOD_##axis, \ + .info_mask_separate =3D BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type =3D BIT(IIO_CHAN_INFO_SCALE), \ + .info_mask_shared_by_type_available =3D BIT(IIO_CHAN_INFO_SCALE), \ + .info_mask_shared_by_all =3D BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .info_mask_shared_by_all_available =3D \ + BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .event_spec =3D adxl367_events, \ + .num_event_specs =3D ARRAY_SIZE(adxl367_events), \ + .scan_index =3D (index), \ + .scan_type =3D { \ + .sign =3D 's', \ + .realbits =3D 14, \ + .storagebits =3D 16, \ + .endianness =3D IIO_BE, \ + }, \ +} + +#define ADXL367_CHANNEL(index, reg, _type) { \ + .type =3D (_type), \ + .address =3D (reg), \ + .info_mask_separate =3D BIT(IIO_CHAN_INFO_RAW) | \ + BIT(IIO_CHAN_INFO_OFFSET) | \ + BIT(IIO_CHAN_INFO_SCALE), \ + .info_mask_shared_by_all =3D BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .scan_index =3D (index), \ + .scan_type =3D { \ + .sign =3D 's', \ + .realbits =3D 14, \ + .storagebits =3D 16, \ + .endianness =3D IIO_BE, \ + }, \ +} + +static const struct iio_chan_spec adxl367_channels[] =3D { + ADXL367_ACCEL_CHANNEL(ADXL367_X_CHANNEL_INDEX, ADXL367_REG_X_DATA_H, X), + ADXL367_ACCEL_CHANNEL(ADXL367_Y_CHANNEL_INDEX, ADXL367_REG_Y_DATA_H, Y), + ADXL367_ACCEL_CHANNEL(ADXL367_Z_CHANNEL_INDEX, ADXL367_REG_Z_DATA_H, Z), + ADXL367_CHANNEL(ADXL367_TEMP_CHANNEL_INDEX, ADXL367_REG_TEMP_DATA_H, + IIO_TEMP), + ADXL367_CHANNEL(ADXL367_EX_ADC_CHANNEL_INDEX, ADXL367_REG_EX_ADC_DATA_H, + IIO_VOLTAGE), +}; + +static int adxl367_verify_devid(struct adxl367_state *st) +{ + unsigned int val; + int ret; + + ret =3D regmap_read_poll_timeout(st->regmap, ADXL367_REG_DEVID, val, + val =3D=3D ADXL367_DEVID_AD, 1000, 10000); + if (ret) + return dev_err_probe(st->dev, -ENODEV, + "Invalid dev id 0x%02X, expected 0x%02X\n", + val, ADXL367_DEVID_AD); + + return 0; +} + +static int adxl367_setup(struct adxl367_state *st) +{ + int ret; + + ret =3D _adxl367_set_act_threshold(st, ADXL367_ACTIVITY, + ADXL367_2G_RANGE_1G); + if (ret) + return ret; + + ret =3D _adxl367_set_act_threshold(st, ADXL367_INACTIVITY, + ADXL367_2G_RANGE_100MG); + if (ret) + return ret; + + ret =3D adxl367_set_act_proc_mode(st, ADXL367_LOOPED); + if (ret) + return ret; + + ret =3D _adxl367_set_odr(st, ADXL367_ODR_400HZ); + if (ret) + return ret; + + ret =3D _adxl367_set_act_time_ms(st, 10); + if (ret) + return ret; + + ret =3D _adxl367_set_inact_time_ms(st, 10000); + if (ret) + return ret; + + return adxl367_set_measure_en(st, true); +} + +static void adxl367_disable_regulators(void *data) +{ + struct adxl367_state *st =3D data; + + regulator_bulk_disable(ARRAY_SIZE(st->regulators), st->regulators); +} + +int adxl367_probe(struct device *dev, const struct adxl367_ops *ops, + void *context, struct regmap *regmap, int irq) +{ + struct iio_dev *indio_dev; + struct adxl367_state *st; + int ret; + + indio_dev =3D devm_iio_device_alloc(dev, sizeof(*st)); + if (!indio_dev) + return -ENOMEM; + + st =3D iio_priv(indio_dev); + st->dev =3D dev; + st->regmap =3D regmap; + st->context =3D context; + st->ops =3D ops; + + mutex_init(&st->lock); + + indio_dev->channels =3D adxl367_channels; + indio_dev->num_channels =3D ARRAY_SIZE(adxl367_channels); + indio_dev->available_scan_masks =3D adxl367_channel_masks; + indio_dev->name =3D "adxl367"; + indio_dev->info =3D &adxl367_info; + indio_dev->modes =3D INDIO_DIRECT_MODE; + + st->regulators[0].supply =3D "vdd"; + st->regulators[1].supply =3D "vddio"; + + ret =3D devm_regulator_bulk_get(st->dev, ARRAY_SIZE(st->regulators), + st->regulators); + if (ret) + return dev_err_probe(st->dev, ret, + "Failed to get regulators\n"); + + ret =3D regulator_bulk_enable(ARRAY_SIZE(st->regulators), st->regulators); + if (ret) + return dev_err_probe(st->dev, ret, + "Failed to enable regulators\n"); + + ret =3D devm_add_action_or_reset(st->dev, adxl367_disable_regulators, st); + if (ret) + return dev_err_probe(st->dev, ret, + "Failed to add regulators disable action\n"); + + ret =3D regmap_write(st->regmap, ADXL367_REG_RESET, ADXL367_RESET_CODE); + if (ret) + return ret; + + ret =3D adxl367_verify_devid(st); + if (ret) + return ret; + + ret =3D adxl367_setup(st); + if (ret) + return ret; + + ret =3D devm_iio_kfifo_buffer_setup_ext(st->dev, indio_dev, + INDIO_BUFFER_SOFTWARE, + &adxl367_buffer_ops, + adxl367_fifo_attributes); + if (ret) + return ret; + + ret =3D devm_request_threaded_irq(st->dev, irq, NULL, + adxl367_irq_handler, IRQF_ONESHOT, + indio_dev->name, indio_dev); + if (ret) + return dev_err_probe(st->dev, ret, "Failed to request irq\n"); + + return devm_iio_device_register(dev, indio_dev); +} +EXPORT_SYMBOL_NS_GPL(adxl367_probe, IIO_ADXL367); + +MODULE_AUTHOR("Cosmin Tanislav "); +MODULE_DESCRIPTION("Analog Devices ADXL367 3-axis accelerometer driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/iio/accel/adxl367.h b/drivers/iio/accel/adxl367.h new file mode 100644 index 000000000000..4a42622149b1 --- /dev/null +++ b/drivers/iio/accel/adxl367.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2021 Analog Devices, Inc. + * Author: Cosmin Tanislav + */ + +#ifndef _ADXL367_H_ +#define _ADXL367_H_ + +#include + +struct device; +struct regmap; + +struct adxl367_ops { + int (*read_fifo)(void *context, __be16 *fifo_buf, + unsigned int fifo_entries); +}; + +int adxl367_probe(struct device *dev, const struct adxl367_ops *ops, + void *context, struct regmap *regmap, int irq); + +#endif /* _ADXL367_H_ */ diff --git a/drivers/iio/accel/adxl367_i2c.c b/drivers/iio/accel/adxl367_i2= c.c new file mode 100644 index 000000000000..3606efa25835 --- /dev/null +++ b/drivers/iio/accel/adxl367_i2c.c @@ -0,0 +1,90 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2021 Analog Devices, Inc. + * Author: Cosmin Tanislav + */ + +#include +#include +#include +#include + +#include "adxl367.h" + +#define ADXL367_I2C_FIFO_DATA 0x42 + +struct adxl367_i2c_state { + struct regmap *regmap; +}; + +static bool adxl367_readable_noinc_reg(struct device *dev, unsigned int re= g) +{ + return reg =3D=3D ADXL367_I2C_FIFO_DATA; +} + +static int adxl367_i2c_read_fifo(void *context, __be16 *fifo_buf, + unsigned int fifo_entries) +{ + struct adxl367_i2c_state *st =3D context; + + return regmap_noinc_read(st->regmap, ADXL367_I2C_FIFO_DATA, fifo_buf, + fifo_entries * sizeof(*fifo_buf)); +} + +static const struct regmap_config adxl367_i2c_regmap_config =3D { + .reg_bits =3D 8, + .val_bits =3D 8, + .readable_noinc_reg =3D adxl367_readable_noinc_reg, +}; + +static const struct adxl367_ops adxl367_i2c_ops =3D { + .read_fifo =3D adxl367_i2c_read_fifo, +}; + +static int adxl367_i2c_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct adxl367_i2c_state *st; + struct regmap *regmap; + + st =3D devm_kzalloc(&client->dev, sizeof(*st), GFP_KERNEL); + if (!st) + return -ENOMEM; + + regmap =3D devm_regmap_init_i2c(client, &adxl367_i2c_regmap_config); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + st->regmap =3D regmap; + + return adxl367_probe(&client->dev, &adxl367_i2c_ops, st, regmap, + client->irq); +} + +static const struct i2c_device_id adxl367_i2c_id[] =3D { + { "adxl367", 0 }, + { }, +}; +MODULE_DEVICE_TABLE(i2c, adxl367_i2c_id); + +static const struct of_device_id adxl367_of_match[] =3D { + { .compatible =3D "adi,adxl367" }, + { }, +}; +MODULE_DEVICE_TABLE(of, adxl367_of_match); + +static struct i2c_driver adxl367_i2c_driver =3D { + .driver =3D { + .name =3D "adxl367_i2c", + .of_match_table =3D adxl367_of_match, + }, + .probe =3D adxl367_i2c_probe, + .id_table =3D adxl367_i2c_id, +}; + +module_i2c_driver(adxl367_i2c_driver); + +MODULE_IMPORT_NS(IIO_ADXL367); +MODULE_AUTHOR("Cosmin Tanislav "); +MODULE_DESCRIPTION("Analog Devices ADXL367 3-axis accelerometer I2C driver= "); +MODULE_LICENSE("GPL"); diff --git a/drivers/iio/accel/adxl367_spi.c b/drivers/iio/accel/adxl367_sp= i.c new file mode 100644 index 000000000000..26dfc821ebbe --- /dev/null +++ b/drivers/iio/accel/adxl367_spi.c @@ -0,0 +1,164 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2021 Analog Devices, Inc. + * Author: Cosmin Tanislav + */ + +#include +#include +#include +#include + +#include "adxl367.h" + +#define ADXL367_SPI_WRITE_COMMAND 0x0A +#define ADXL367_SPI_READ_COMMAND 0x0B +#define ADXL367_SPI_FIFO_COMMAND 0x0D + +struct adxl367_spi_state { + struct spi_device *spi; + + struct spi_message reg_write_msg; + struct spi_transfer reg_write_xfer[2]; + + struct spi_message reg_read_msg; + struct spi_transfer reg_read_xfer[2]; + + struct spi_message fifo_msg; + struct spi_transfer fifo_xfer[2]; + + /* + * DMA (thus cache coherency maintenance) requires the + * transfer buffers to live in their own cache lines. + */ + u8 reg_write_tx_buf[1] ____cacheline_aligned; + u8 reg_read_tx_buf[2]; + u8 fifo_tx_buf[1]; +}; + +static int adxl367_read_fifo(void *context, __be16 *fifo_buf, + unsigned int fifo_entries) +{ + struct adxl367_spi_state *st =3D context; + + st->fifo_xfer[1].rx_buf =3D fifo_buf; + st->fifo_xfer[1].len =3D fifo_entries * sizeof(*fifo_buf); + + return spi_sync(st->spi, &st->fifo_msg); +} + +static int adxl367_read(void *context, const void *reg_buf, size_t reg_siz= e, + void *val_buf, size_t val_size) +{ + struct adxl367_spi_state *st =3D context; + u8 reg =3D ((const u8 *)reg_buf)[0]; + + st->reg_read_tx_buf[1] =3D reg; + st->reg_read_xfer[1].rx_buf =3D val_buf; + st->reg_read_xfer[1].len =3D val_size; + + return spi_sync(st->spi, &st->reg_read_msg); +} + +static int adxl367_write(void *context, const void *val_buf, size_t val_si= ze) +{ + struct adxl367_spi_state *st =3D context; + + st->reg_write_xfer[1].tx_buf =3D val_buf; + st->reg_write_xfer[1].len =3D val_size; + + return spi_sync(st->spi, &st->reg_write_msg); +} + +static struct regmap_bus adxl367_spi_regmap_bus =3D { + .read =3D adxl367_read, + .write =3D adxl367_write, +}; + +static const struct regmap_config adxl367_spi_regmap_config =3D { + .reg_bits =3D 8, + .val_bits =3D 8, +}; + +static const struct adxl367_ops adxl367_spi_ops =3D { + .read_fifo =3D adxl367_read_fifo, +}; + +static int adxl367_spi_probe(struct spi_device *spi) +{ + struct adxl367_spi_state *st; + struct regmap *regmap; + + st =3D devm_kzalloc(&spi->dev, sizeof(*st), GFP_KERNEL); + if (!st) + return -ENOMEM; + + st->spi =3D spi; + + /* + * Xfer: [XFR1] [ XFR2 ] + * Master: 0x0A ADDR DATA0 DATA1 ... DATAN + * Slave: .... .......................... + */ + st->reg_write_tx_buf[0] =3D ADXL367_SPI_WRITE_COMMAND; + st->reg_write_xfer[0].tx_buf =3D st->reg_write_tx_buf; + st->reg_write_xfer[0].len =3D sizeof(st->reg_write_tx_buf); + spi_message_init_with_transfers(&st->reg_write_msg, + st->reg_write_xfer, 2); + + /* + * Xfer: [ XFR1 ] [ XFR2 ] + * Master: 0x0B ADDR ..................... + * Slave: ......... DATA0 DATA1 ... DATAN + */ + st->reg_read_tx_buf[0] =3D ADXL367_SPI_READ_COMMAND; + st->reg_read_xfer[0].tx_buf =3D st->reg_read_tx_buf; + st->reg_read_xfer[0].len =3D sizeof(st->reg_read_tx_buf); + spi_message_init_with_transfers(&st->reg_read_msg, + st->reg_read_xfer, 2); + + /* + * Xfer: [XFR1] [ XFR2 ] + * Master: 0x0D ..................... + * Slave: .... DATA0 DATA1 ... DATAN + */ + st->fifo_tx_buf[0] =3D ADXL367_SPI_FIFO_COMMAND; + st->fifo_xfer[0].tx_buf =3D st->fifo_tx_buf; + st->fifo_xfer[0].len =3D sizeof(st->fifo_tx_buf); + spi_message_init_with_transfers(&st->fifo_msg, st->fifo_xfer, 2); + + regmap =3D devm_regmap_init(&spi->dev, &adxl367_spi_regmap_bus, st, + &adxl367_spi_regmap_config); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + return adxl367_probe(&spi->dev, &adxl367_spi_ops, st, regmap, spi->irq); +} + +static const struct spi_device_id adxl367_spi_id[] =3D { + { "adxl367", 0 }, + { }, +}; +MODULE_DEVICE_TABLE(spi, adxl367_spi_id); + +static const struct of_device_id adxl367_of_match[] =3D { + { .compatible =3D "adi,adxl367" }, + { }, +}; +MODULE_DEVICE_TABLE(of, adxl367_of_match); + +static struct spi_driver adxl367_spi_driver =3D { + .driver =3D { + .name =3D "adxl367_spi", + .of_match_table =3D adxl367_of_match, + }, + .probe =3D adxl367_spi_probe, + .id_table =3D adxl367_spi_id, +}; + +module_spi_driver(adxl367_spi_driver); + +MODULE_IMPORT_NS(IIO_ADXL367); +MODULE_AUTHOR("Cosmin Tanislav "); +MODULE_DESCRIPTION("Analog Devices ADXL367 3-axis accelerometer SPI driver= "); +MODULE_LICENSE("GPL"); --=20 2.35.1