From patchwork Mon Apr 18 19:28:51 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonathan Cameron X-Patchwork-Id: 12817059 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id D3923C433EF for ; Mon, 18 Apr 2022 19:21:15 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1347651AbiDRTXy (ORCPT ); Mon, 18 Apr 2022 15:23:54 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44132 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1347654AbiDRTXx (ORCPT ); Mon, 18 Apr 2022 15:23:53 -0400 Received: from ams.source.kernel.org (ams.source.kernel.org [145.40.68.75]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3489620F41 for ; Mon, 18 Apr 2022 12:21:12 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id DD9EBB8105F for ; Mon, 18 Apr 2022 19:21:10 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 15C2DC385A7; Mon, 18 Apr 2022 19:21:07 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1650309669; bh=DjGNohPhHCYecnNxT0akgHQjeQMgRuKqfumJ63YbeHQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=eqWW0nE5h7yOT1oKPm/eRp7RjWiUkLluQkhXiYg/V2u8cQsAh+4EItHxSrR2QssaP GgCOMLtHeDGTGguHKCwRZ2nR+kIXAM1/QyCrHdH4S8E5QrkgZZBFEJCnRXoWwkN1Pa vl7vG9x39km+2LEIsXDhzh2hays4IqyRCFsS3aiue/oQuiHsGDQGghHlXpd5nZsujW Pwuk6q8/blHL9TWEhggT46fXx74xnNm3SxULflmBnDotoUdQ95+Lx9yxv3G5kg1b4F 2PqcWUNQZDXJ9LtHQP125gDwgyI0sRpbxikdYyW5zvP/dohV1VV2MOAQ70NJCGFn9o 7SZ07FV1e+7Pw== From: Jonathan Cameron To: linux-iio@vger.kernel.org Cc: Michael Hennerich , Lars-Peter Clausen , Vincent Whitchurch , Jonathan Cameron Subject: [PATCH 01/17] iio: core: Increase precision of IIO_VAL_FRACTIONAL_LOG2 Date: Mon, 18 Apr 2022 20:28:51 +0100 Message-Id: <20220418192907.763933-2-jic23@kernel.org> X-Mailer: git-send-email 2.35.3 In-Reply-To: <20220418192907.763933-1-jic23@kernel.org> References: <20220418192907.763933-1-jic23@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org From: Jonathan Cameron With some high resolution sensors such as the ad7746 the build up of error when multiplying the _raw and _scale values together can be significant. Reduce this affect by providing additional resolution in both calculation and formatting of result. Signed-off-by: Jonathan Cameron --- drivers/iio/industrialio-core.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index 2f48e9a97274..d831835770da 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -683,14 +683,21 @@ static ssize_t __iio_format_value(char *buf, size_t offset, unsigned int type, else return sysfs_emit_at(buf, offset, "%d.%09u", tmp0, abs(tmp1)); - case IIO_VAL_FRACTIONAL_LOG2: - tmp2 = shift_right((s64)vals[0] * 1000000000LL, vals[1]); - tmp0 = (int)div_s64_rem(tmp2, 1000000000LL, &tmp1); - if (tmp0 == 0 && tmp2 < 0) - return sysfs_emit_at(buf, offset, "-0.%09u", abs(tmp1)); - else - return sysfs_emit_at(buf, offset, "%d.%09u", tmp0, - abs(tmp1)); + case IIO_VAL_FRACTIONAL_LOG2: { + u64 t1, t2; + int integer; + bool neg = vals[0] < 0; + + t1 = shift_right((u64)abs(vals[0]) * 1000000000000ULL, vals[1]); + integer = (int)div64_u64_rem(t1, 1000000000000ULL, &t2); + if (integer == 0 && neg) + return sysfs_emit_at(buf, offset, "-0.%012llu", abs(t2)); + if (neg) + integer *= -1; + return sysfs_emit_at(buf, offset, "%d.%012llu", integer, + abs(t2)); + } + } case IIO_VAL_INT_MULTIPLE: { int i; From patchwork Mon Apr 18 19:28:52 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonathan Cameron X-Patchwork-Id: 12817060 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 96492C433FE for ; Mon, 18 Apr 2022 19:21:16 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1347654AbiDRTXy (ORCPT ); Mon, 18 Apr 2022 15:23:54 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44232 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1347666AbiDRTXy (ORCPT ); Mon, 18 Apr 2022 15:23:54 -0400 Received: from ams.source.kernel.org (ams.source.kernel.org [145.40.68.75]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id ADD8B2BB2E for ; Mon, 18 Apr 2022 12:21:14 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id 55C21B8108B for ; Mon, 18 Apr 2022 19:21:13 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 53720C385AA; Mon, 18 Apr 2022 19:21:09 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1650309672; bh=BDUGp7Hfp4wkmU/H3antyBvzgZduQuyIO3AfaQY2suk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=K/VkXbdrWfyq8XK6zMvp44WaMwVGVGQ/uIGjmzAy9V2CYMPSYWdk8Vu0arDCj7kpD Bxj74beC65/3Gfl7m3+7yoRrThnAWIdOECXzXX9s5Bm14D9L6LSWuCKCEdT9ZacbaD 7b8TwKo4/X/9wrQQmMVtW6IEexSie9rpIGBnVj7bqQsFdwN6RqObAe8SvS65OZpIy5 JBzDrFSVskVcN+k6ly1TxQBCS3ILRZqFWCCbXQ/RITvFr7tqyi2bRojOVKOwik2l5M L+K6nyJYpPtTT7uhSrRN0hwmgYihvgebdr0clNOfRIxjzDLW/PUTWfhSbrUno1NNim j9QsspEeGzwIQ== From: Jonathan Cameron To: linux-iio@vger.kernel.org Cc: Michael Hennerich , Lars-Peter Clausen , Vincent Whitchurch , Jonathan Cameron Subject: [PATCH 02/17] iio: ABI: Fix wrong format of differential capacitance channel ABI. Date: Mon, 18 Apr 2022 20:28:52 +0100 Message-Id: <20220418192907.763933-3-jic23@kernel.org> X-Mailer: git-send-email 2.35.3 In-Reply-To: <20220418192907.763933-1-jic23@kernel.org> References: <20220418192907.763933-1-jic23@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org From: Jonathan Cameron in_ only occurs once in these attributes. Signed-off-by: Jonathan Cameron --- Documentation/ABI/testing/sysfs-bus-iio | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio index d4ccc68fdcf0..b19ff517e5d6 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio +++ b/Documentation/ABI/testing/sysfs-bus-iio @@ -188,7 +188,7 @@ Description: Raw capacitance measurement from channel Y. Units after application of scale and offset are nanofarads. -What: /sys/.../iio:deviceX/in_capacitanceY-in_capacitanceZ_raw +What: /sys/.../iio:deviceX/in_capacitanceY-capacitanceZ_raw KernelVersion: 3.2 Contact: linux-iio@vger.kernel.org Description: From patchwork Mon Apr 18 19:28:53 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonathan Cameron X-Patchwork-Id: 12817061 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2C06CC433EF for ; Mon, 18 Apr 2022 19:21:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1347666AbiDRTXz (ORCPT ); Mon, 18 Apr 2022 15:23:55 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44278 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1347668AbiDRTXy (ORCPT ); Mon, 18 Apr 2022 15:23:54 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [IPv6:2604:1380:4641:c500::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4784E32EFB for ; Mon, 18 Apr 2022 12:21:15 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id D72C860E0A for ; Mon, 18 Apr 2022 19:21:14 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 91ED5C385A1; Mon, 18 Apr 2022 19:21:12 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1650309674; bh=M1tByr7zU6onOJijIzxftHivBdnr0cCoL/rMK4QFvnE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=dToA6+rKT2OAMN8FQpPHggE+pZVbAINWdqWjI8kUunBF1VjYRm5+25jz+XF2ZV+GE doN1SsrO2NHc2FdKLWRg0WSgBzajWiRPVsvvuGr1ZNLvXjYu7QjyBwbAFI4QPW8wy8 h1w92u5ruhQXD7lthvcxocLCHAKsGmkKdY6Om94tSHDCeXbcEA+zK0DQ1Fzq7wR5Rl MXXlba6eTx9Xus4M+52MdqynhMFpVBYKF+BVPZ/0daCqG8KOHnMbK8B/Rv9fDrv+mq VR3DWjn5rLBZyl84RM09Py2cWeffr6wQsNDOcZ5q5wSo7DXG1wRx3VW0uL4ZQJNtrs C/mXCsqMgSgQA== From: Jonathan Cameron To: linux-iio@vger.kernel.org Cc: Michael Hennerich , Lars-Peter Clausen , Vincent Whitchurch , Jonathan Cameron Subject: [PATCH 03/17] staging: iio: cdc: ad7746: Use explicit be24 handling. Date: Mon, 18 Apr 2022 20:28:53 +0100 Message-Id: <20220418192907.763933-4-jic23@kernel.org> X-Mailer: git-send-email 2.35.3 In-Reply-To: <20220418192907.763933-1-jic23@kernel.org> References: <20220418192907.763933-1-jic23@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org From: Jonathan Cameron Change from fiddly local implementation of be24 to cpu endian conversion by reading into a 3 byte buffer and using get_unaligned_be24() Signed-off-by: Jonathan Cameron --- drivers/staging/iio/cdc/ad7746.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/staging/iio/cdc/ad7746.c b/drivers/staging/iio/cdc/ad7746.c index 71c709771676..1f510610ed32 100644 --- a/drivers/staging/iio/cdc/ad7746.c +++ b/drivers/staging/iio/cdc/ad7746.c @@ -95,10 +95,7 @@ struct ad7746_chip_info { u8 capdac[2][2]; s8 capdac_set; - union { - __be32 d32; - u8 d8[4]; - } data ____cacheline_aligned; + u8 data[3] ____cacheline_aligned; }; enum ad7746_chan { @@ -547,12 +544,12 @@ static int ad7746_read_raw(struct iio_dev *indio_dev, ret = i2c_smbus_read_i2c_block_data(chip->client, chan->address >> 8, 3, - &chip->data.d8[1]); + chip->data); if (ret < 0) goto out; - *val = (be32_to_cpu(chip->data.d32) & 0xFFFFFF) - 0x800000; + *val = get_unaligned_be24(chip->data) - 0x800000; switch (chan->type) { case IIO_TEMP: From patchwork Mon Apr 18 19:28:54 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonathan Cameron X-Patchwork-Id: 12817062 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 23A72C433EF for ; Mon, 18 Apr 2022 19:21:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1347668AbiDRTX7 (ORCPT ); Mon, 18 Apr 2022 15:23:59 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44330 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1347671AbiDRTX5 (ORCPT ); Mon, 18 Apr 2022 15:23:57 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B852335862 for ; Mon, 18 Apr 2022 12:21:17 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 202FE60E9A for ; Mon, 18 Apr 2022 19:21:17 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id D00FAC385AA; Mon, 18 Apr 2022 19:21:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1650309676; bh=ikMVn+SMOgW3yNKey75lSpwVSFSGho5UFplLdRuXp78=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=g3EY/hmpdTi1F71d5d5SP0wMnNkS8S5xtuWXwpMuxe68hfdcdZrEP6N4W7UmG+LEK DoLxTfLfG7+g5ZciSicZOQOHloYDpez0nz4KkSYKZOTIp6f3/K4aOdcOZSfH7Qs49m EnpcOABXXCumZDTW9mPRGk4JtJaDLpkogtyJIZpTGndAm6ijwtvO/2RItm3hUXPZJ5 4+ELLAa3+s4Y0uYFhZAed9rPFkZsu2Z67NZ8hrBBKKbO7decc+53BAdQZO3LF4MbRt f408m1JlUpzrVnqidSonkmOB95IJCOSRJnjOSwkKWzWDId+Qp0lrUClZULFkEAi9yL Hkq2499UnIChA== From: Jonathan Cameron To: linux-iio@vger.kernel.org Cc: Michael Hennerich , Lars-Peter Clausen , Vincent Whitchurch , Jonathan Cameron Subject: [PATCH 04/17] staging: iio: cdc: ad7746: Push handling of supply voltage scale to userspace. Date: Mon, 18 Apr 2022 20:28:54 +0100 Message-Id: <20220418192907.763933-5-jic23@kernel.org> X-Mailer: git-send-email 2.35.3 In-Reply-To: <20220418192907.763933-1-jic23@kernel.org> References: <20220418192907.763933-1-jic23@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org From: Jonathan Cameron The supply voltage is attenuated by 6 before being fed to the ADC. Handle this explcitly rather than premultiplying the _raw value by 6. Signed-off-by: Jonathan Cameron --- drivers/staging/iio/cdc/ad7746.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/drivers/staging/iio/cdc/ad7746.c b/drivers/staging/iio/cdc/ad7746.c index 1f510610ed32..1379caf88b83 100644 --- a/drivers/staging/iio/cdc/ad7746.c +++ b/drivers/staging/iio/cdc/ad7746.c @@ -114,9 +114,8 @@ static const struct iio_chan_spec ad7746_channels[] = { .type = IIO_VOLTAGE, .indexed = 1, .channel = 0, - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), - .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | - BIT(IIO_CHAN_INFO_SAMP_FREQ), + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ), .address = AD7746_REG_VT_DATA_HIGH << 8 | AD7746_VTSETUP_VTMD_EXT_VIN, }, @@ -125,9 +124,8 @@ static const struct iio_chan_spec ad7746_channels[] = { .indexed = 1, .channel = 1, .extend_name = "supply", - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), - .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | - BIT(IIO_CHAN_INFO_SAMP_FREQ), + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ), .address = AD7746_REG_VT_DATA_HIGH << 8 | AD7746_VTSETUP_VTMD_VDD_MON, }, @@ -559,10 +557,6 @@ static int ad7746_read_raw(struct iio_dev *indio_dev, */ *val = (*val * 125) / 256; break; - case IIO_VOLTAGE: - if (chan->channel == 1) /* supply_raw*/ - *val = *val * 6; - break; default: break; } @@ -617,6 +611,8 @@ static int ad7746_read_raw(struct iio_dev *indio_dev, case IIO_VOLTAGE: /* 1170mV / 2^23 */ *val = 1170; + if (chan->channel == 1) + *val *= 6; *val2 = 23; ret = IIO_VAL_FRACTIONAL_LOG2; break; From patchwork Mon Apr 18 19:28:55 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonathan Cameron X-Patchwork-Id: 12817063 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8A34BC433F5 for ; Mon, 18 Apr 2022 19:21:25 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1347669AbiDRTYC (ORCPT ); Mon, 18 Apr 2022 15:24:02 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44422 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1347670AbiDRTYB (ORCPT ); Mon, 18 Apr 2022 15:24:01 -0400 Received: from ams.source.kernel.org (ams.source.kernel.org [145.40.68.75]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6E4AE35862 for ; Mon, 18 Apr 2022 12:21:21 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id 0CAECB8105F for ; Mon, 18 Apr 2022 19:21:20 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 187EFC385A1; Mon, 18 Apr 2022 19:21:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1650309678; bh=UlYg/e/6eH/JDXpxBmVlPSaAqcvK/301oJ5fVBiYHFw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=V7sH1l/Djh6c34eseRRWqiKRU1N1uX0ZQvGYBygaeA0ZKtBW+KfsN9Htsi4IXp/u1 pJOgaKFzI69O4sy+DdH3KUliO79oQIeBoMemdwEJ0B+Mw9RxKf9QJSNocxWGA9McoM 1ll8E6jDfAkmWQU5mos9NtL5b7YBoYmBBw1Vd04vP0p1wYBPCXnQTdIeHO4qV9O2kl qBx7Jd8duUEl9Pg12IWz1OnxKNYi6m6HdGsRLUu0mMQZollcFVUBC/xl8rgXsE6/Kz Wfy6QMh4Zuud5aU4Hsg1y8zrOu7HcG6tGHPF9TyZYNlHyzEZQwCpSOFOq5lvW+Ngaq m9hdj6/68rhLA== From: Jonathan Cameron To: linux-iio@vger.kernel.org Cc: Michael Hennerich , Lars-Peter Clausen , Vincent Whitchurch , Jonathan Cameron Subject: [PATCH 05/17] staging: iio: cdc: ad7746: Use local buffer for multi byte reads. Date: Mon, 18 Apr 2022 20:28:55 +0100 Message-Id: <20220418192907.763933-6-jic23@kernel.org> X-Mailer: git-send-email 2.35.3 In-Reply-To: <20220418192907.763933-1-jic23@kernel.org> References: <20220418192907.763933-1-jic23@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org From: Jonathan Cameron I2C does not require DMA safe buffers so there is no need to ensure the buffers are in their own cacheline. Hence simplify things by using a local variable instead of embedding the buffer in the chip info structure. Signed-off-by: Jonathan Cameron --- drivers/staging/iio/cdc/ad7746.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/staging/iio/cdc/ad7746.c b/drivers/staging/iio/cdc/ad7746.c index 1379caf88b83..e4b882586891 100644 --- a/drivers/staging/iio/cdc/ad7746.c +++ b/drivers/staging/iio/cdc/ad7746.c @@ -94,8 +94,6 @@ struct ad7746_chip_info { u8 vt_setup; u8 capdac[2][2]; s8 capdac_set; - - u8 data[3] ____cacheline_aligned; }; enum ad7746_chan { @@ -520,6 +518,7 @@ static int ad7746_read_raw(struct iio_dev *indio_dev, struct ad7746_chip_info *chip = iio_priv(indio_dev); int ret, delay, idx; u8 regval, reg; + u8 data[3]; mutex_lock(&chip->lock); @@ -542,12 +541,12 @@ static int ad7746_read_raw(struct iio_dev *indio_dev, ret = i2c_smbus_read_i2c_block_data(chip->client, chan->address >> 8, 3, - chip->data); + data); if (ret < 0) goto out; - *val = get_unaligned_be24(chip->data) - 0x800000; + *val = get_unaligned_be24(data) - 0x800000; switch (chan->type) { case IIO_TEMP: From patchwork Mon Apr 18 19:28:56 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonathan Cameron X-Patchwork-Id: 12817064 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id BC298C433EF for ; Mon, 18 Apr 2022 19:21:27 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1347670AbiDRTYF (ORCPT ); Mon, 18 Apr 2022 15:24:05 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44484 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1347673AbiDRTYD (ORCPT ); Mon, 18 Apr 2022 15:24:03 -0400 Received: from ams.source.kernel.org (ams.source.kernel.org [145.40.68.75]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9A8BC35862 for ; Mon, 18 Apr 2022 12:21:23 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id 49D98B8108C for ; Mon, 18 Apr 2022 19:21:22 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 3E986C385AA; Mon, 18 Apr 2022 19:21:19 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1650309680; bh=ogcRt7PB/AZsDLc4SrFvNvZ+Kb4tStRL7ozwnmVE3/o=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=N2AVeLADt0vWmlR+poP+MTV9N+0uN3ryGpy/PCmnkc6Hmu2ld8KQy2ejY+2XVN4KO dfqJx/xu41dIakWBcxdtKCh23SbdLrBhKC3+ssthcM90fiLb5HttbupHtFwSu+NZuJ 6BMuIgO3Erd9w51vpUDLE15NqB+y6bPek4n+i4VeKy3qDXmDtEFZuwhw/v2jjEIkrt QpU/SsF/phBKtAj+Iw0geLinVYPVp0kzFgEUWGaAYeqrm5ZrYe1FO9bznmJ1DzOyCN Q9L4Oz7Pox+dfD/bXKP42xH3G9QQknIyGoxs2KiOUYPHWA4Z4iBG6ep8vCr6mXNzv3 8+sOp8GBdGBAw== From: Jonathan Cameron To: linux-iio@vger.kernel.org Cc: Michael Hennerich , Lars-Peter Clausen , Vincent Whitchurch , Jonathan Cameron Subject: [PATCH 06/17] staging: iio: cdc: ad7746: Factor out ad7746_read_channel() Date: Mon, 18 Apr 2022 20:28:56 +0100 Message-Id: <20220418192907.763933-7-jic23@kernel.org> X-Mailer: git-send-email 2.35.3 In-Reply-To: <20220418192907.763933-1-jic23@kernel.org> References: <20220418192907.763933-1-jic23@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org From: Jonathan Cameron Reduce deep indenting and simplify the locking cleanup that follows. Signed-off-by: Jonathan Cameron --- drivers/staging/iio/cdc/ad7746.c | 79 ++++++++++++++++---------------- 1 file changed, 40 insertions(+), 39 deletions(-) diff --git a/drivers/staging/iio/cdc/ad7746.c b/drivers/staging/iio/cdc/ad7746.c index e4b882586891..6b9530bd12cc 100644 --- a/drivers/staging/iio/cdc/ad7746.c +++ b/drivers/staging/iio/cdc/ad7746.c @@ -500,14 +500,47 @@ static int ad7746_write_raw(struct iio_dev *indio_dev, default: ret = -EINVAL; } +static int ad7746_read_channel(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val) +{ + struct ad7746_chip_info *chip = iio_priv(indio_dev); + int ret, delay; + u8 data[3]; + u8 regval; + + ret = ad7746_select_channel(indio_dev, chan); + if (ret < 0) + return ret; + delay = ret; + + regval = chip->config | AD7746_CONF_MODE_SINGLE_CONV; + ret = i2c_smbus_write_byte_data(chip->client, AD7746_REG_CFG, regval); + if (ret < 0) + return ret; + + msleep(delay); + /* Now read the actual register */ + ret = i2c_smbus_read_i2c_block_data(chip->client, chan->address >> 8, + 3, data); + if (ret < 0) + return ret; + + *val = get_unaligned_be24(data) - 0x800000; + + switch (chan->type) { + case IIO_TEMP: + /* + * temperature in milli degrees Celsius + * T = ((*val / 2048) - 4096) * 1000 + */ + *val = (*val * 125) / 256; break; default: - ret = -EINVAL; + break; } -out: - mutex_unlock(&chip->lock); - return ret; + return 0; } static int ad7746_read_raw(struct iio_dev *indio_dev, @@ -516,49 +549,17 @@ static int ad7746_read_raw(struct iio_dev *indio_dev, long mask) { struct ad7746_chip_info *chip = iio_priv(indio_dev); - int ret, delay, idx; - u8 regval, reg; - u8 data[3]; + int ret, idx; + u8 reg; mutex_lock(&chip->lock); switch (mask) { case IIO_CHAN_INFO_RAW: case IIO_CHAN_INFO_PROCESSED: - ret = ad7746_select_channel(indio_dev, chan); + ret = ad7746_read_channel(indio_dev, chan, val); if (ret < 0) goto out; - delay = ret; - - regval = chip->config | AD7746_CONF_MODE_SINGLE_CONV; - ret = i2c_smbus_write_byte_data(chip->client, AD7746_REG_CFG, - regval); - if (ret < 0) - goto out; - - msleep(delay); - /* Now read the actual register */ - - ret = i2c_smbus_read_i2c_block_data(chip->client, - chan->address >> 8, 3, - data); - - if (ret < 0) - goto out; - - *val = get_unaligned_be24(data) - 0x800000; - - switch (chan->type) { - case IIO_TEMP: - /* - * temperature in milli degrees Celsius - * T = ((*val / 2048) - 4096) * 1000 - */ - *val = (*val * 125) / 256; - break; - default: - break; - } ret = IIO_VAL_INT; break; From patchwork Mon Apr 18 19:28:57 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonathan Cameron X-Patchwork-Id: 12817065 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1CB7AC433FE for ; Mon, 18 Apr 2022 19:21:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1347672AbiDRTYG (ORCPT ); Mon, 18 Apr 2022 15:24:06 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44490 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1347674AbiDRTYE (ORCPT ); Mon, 18 Apr 2022 15:24:04 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0F93F35A8C for ; Mon, 18 Apr 2022 12:21:24 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 8A4B860E16 for ; Mon, 18 Apr 2022 19:21:23 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 7AE8DC385A7; Mon, 18 Apr 2022 19:21:21 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1650309683; bh=AvRxMWjL36xsW/detzEsgm93yFyLX8h3t7CPSaHRBAc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=LWZZgProfd8BsYoPvpBtQNk/xJPRndm06Cv0JNGN9P1881s2WXTzWX8IVNvT7akdm kqyu3d1hGvtc7FKuY5vODfoOyxxTw/Ooye7iFsnsVtqqNOT4AMci5iW2u5fiLqXRLe gL9oZO4esnwlIV9NLgjE7UJ3yvPUs83BN5hrT+lSFQrDPZDSMDcGQI8mmaj6hkb5bt UWnGPbv0ZVJet5hGRWnPmRci2MVg8JBwpE18OnDoqr2UISkwRHASPq90Qctk8JPPBZ DWLsP0ch6ELFcA2fOFBAORasgDrUxN5L7ykgKYPkJFfUMFm3ADLoaYYDAcrJS7EXSA DtbPKEyfcXYnw== From: Jonathan Cameron To: linux-iio@vger.kernel.org Cc: Michael Hennerich , Lars-Peter Clausen , Vincent Whitchurch , Jonathan Cameron Subject: [PATCH 07/17] staging: iio: cdc: ad7764: Push locking down into case statements in read/write_raw Date: Mon, 18 Apr 2022 20:28:57 +0100 Message-Id: <20220418192907.763933-8-jic23@kernel.org> X-Mailer: git-send-email 2.35.3 In-Reply-To: <20220418192907.763933-1-jic23@kernel.org> References: <20220418192907.763933-1-jic23@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org From: Jonathan Cameron Not all paths require any locking at all. So to simplify the removal of such locking push the locks down into the individual case statements. Signed-off-by: Jonathan Cameron --- drivers/staging/iio/cdc/ad7746.c | 125 ++++++++++++++----------------- 1 file changed, 58 insertions(+), 67 deletions(-) diff --git a/drivers/staging/iio/cdc/ad7746.c b/drivers/staging/iio/cdc/ad7746.c index 6b9530bd12cc..34e19677d1fe 100644 --- a/drivers/staging/iio/cdc/ad7746.c +++ b/drivers/staging/iio/cdc/ad7746.c @@ -418,14 +418,10 @@ static int ad7746_write_raw(struct iio_dev *indio_dev, struct ad7746_chip_info *chip = iio_priv(indio_dev); int ret, reg; - mutex_lock(&chip->lock); - switch (mask) { case IIO_CHAN_INFO_CALIBSCALE: - if (val != 1) { - ret = -EINVAL; - goto out; - } + if (val != 1) + return -EINVAL; val = (val2 * 1024) / 15625; @@ -437,33 +433,31 @@ static int ad7746_write_raw(struct iio_dev *indio_dev, reg = AD7746_REG_VOLT_GAINH; break; default: - ret = -EINVAL; - goto out; + return -EINVAL; } + mutex_lock(&chip->lock); ret = i2c_smbus_write_word_swapped(chip->client, reg, val); + mutex_unlock(&chip->lock); if (ret < 0) - goto out; + return ret; - ret = 0; - break; + return 0; case IIO_CHAN_INFO_CALIBBIAS: - if (val < 0 || val > 0xFFFF) { - ret = -EINVAL; - goto out; - } + if (val < 0 || val > 0xFFFF) + return -EINVAL; + + mutex_lock(&chip->lock); ret = i2c_smbus_write_word_swapped(chip->client, AD7746_REG_CAP_OFFH, val); + mutex_unlock(&chip->lock); if (ret < 0) - goto out; + return ret; - ret = 0; - break; + return 0; case IIO_CHAN_INFO_OFFSET: - if (val < 0 || val > 43008000) { /* 21pF */ - ret = -EINVAL; - goto out; - } + if (val < 0 || val > 43008000) /* 21pF */ + return -EINVAL; /* * CAPDAC Scale = 21pF_typ / 127 @@ -472,34 +466,43 @@ static int ad7746_write_raw(struct iio_dev *indio_dev, */ val /= 338646; - + mutex_lock(&chip->lock); chip->capdac[chan->channel][chan->differential] = val > 0 ? AD7746_CAPDAC_DACP(val) | AD7746_CAPDAC_DACEN : 0; ret = ad7746_set_capdac(chip, chan->channel); - if (ret < 0) - goto out; + if (ret < 0) { + mutex_unlock(&chip->lock); + return ret; + } chip->capdac_set = chan->channel; + mutex_unlock(&chip->lock); - ret = 0; - break; + return 0; case IIO_CHAN_INFO_SAMP_FREQ: - if (val2) { - ret = -EINVAL; - goto out; - } + if (val2) + return -EINVAL; switch (chan->type) { case IIO_CAPACITANCE: + mutex_lock(&chip->lock); ret = ad7746_store_cap_filter_rate_setup(chip, val); - break; + mutex_unlock(&chip->lock); + return ret; case IIO_VOLTAGE: + mutex_lock(&chip->lock); ret = ad7746_store_vt_filter_rate_setup(chip, val); - break; + mutex_unlock(&chip->lock); + return ret; default: - ret = -EINVAL; + return -EINVAL; } + default: + return -EINVAL; + } +} + static int ad7746_read_channel(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val) @@ -552,17 +555,16 @@ static int ad7746_read_raw(struct iio_dev *indio_dev, int ret, idx; u8 reg; - mutex_lock(&chip->lock); - switch (mask) { case IIO_CHAN_INFO_RAW: case IIO_CHAN_INFO_PROCESSED: + mutex_lock(&chip->lock); ret = ad7746_read_channel(indio_dev, chan, val); + mutex_unlock(&chip->lock); if (ret < 0) - goto out; + return ret; - ret = IIO_VAL_INT; - break; + return IIO_VAL_INT; case IIO_CHAN_INFO_CALIBSCALE: switch (chan->type) { case IIO_CAPACITANCE: @@ -572,80 +574,69 @@ static int ad7746_read_raw(struct iio_dev *indio_dev, reg = AD7746_REG_VOLT_GAINH; break; default: - ret = -EINVAL; - goto out; + return -EINVAL; } + mutex_lock(&chip->lock); ret = i2c_smbus_read_word_swapped(chip->client, reg); + mutex_unlock(&chip->lock); if (ret < 0) - goto out; + return ret; /* 1 + gain_val / 2^16 */ *val = 1; *val2 = (15625 * ret) / 1024; - ret = IIO_VAL_INT_PLUS_MICRO; - break; + return IIO_VAL_INT_PLUS_MICRO; case IIO_CHAN_INFO_CALIBBIAS: + mutex_lock(&chip->lock); ret = i2c_smbus_read_word_swapped(chip->client, AD7746_REG_CAP_OFFH); + mutex_unlock(&chip->lock); if (ret < 0) - goto out; + return ret; *val = ret; - ret = IIO_VAL_INT; - break; + return IIO_VAL_INT; case IIO_CHAN_INFO_OFFSET: *val = AD7746_CAPDAC_DACP(chip->capdac[chan->channel] [chan->differential]) * 338646; - ret = IIO_VAL_INT; - break; + return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: switch (chan->type) { case IIO_CAPACITANCE: /* 8.192pf / 2^24 */ *val = 0; *val2 = 488; - ret = IIO_VAL_INT_PLUS_NANO; - break; + return IIO_VAL_INT_PLUS_NANO; case IIO_VOLTAGE: /* 1170mV / 2^23 */ *val = 1170; if (chan->channel == 1) *val *= 6; *val2 = 23; - ret = IIO_VAL_FRACTIONAL_LOG2; - break; + return IIO_VAL_FRACTIONAL_LOG2; default: - ret = -EINVAL; - break; + return -EINVAL; } - - break; case IIO_CHAN_INFO_SAMP_FREQ: switch (chan->type) { case IIO_CAPACITANCE: idx = (chip->config & AD7746_CONF_CAPFS_MASK) >> AD7746_CONF_CAPFS_SHIFT; *val = ad7746_cap_filter_rate_table[idx][0]; - ret = IIO_VAL_INT; - break; + return IIO_VAL_INT; case IIO_VOLTAGE: idx = (chip->config & AD7746_CONF_VTFS_MASK) >> AD7746_CONF_VTFS_SHIFT; *val = ad7746_vt_filter_rate_table[idx][0]; - ret = IIO_VAL_INT; - break; + return IIO_VAL_INT; default: - ret = -EINVAL; + return -EINVAL; } - break; default: - ret = -EINVAL; + return -EINVAL; } -out: - mutex_unlock(&chip->lock); - return ret; } static const struct iio_info ad7746_info = { From patchwork Mon Apr 18 19:28:58 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonathan Cameron X-Patchwork-Id: 12817066 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 55E25C433F5 for ; Mon, 18 Apr 2022 19:21:29 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230338AbiDRTYH (ORCPT ); Mon, 18 Apr 2022 15:24:07 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44552 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1347675AbiDRTYG (ORCPT ); Mon, 18 Apr 2022 15:24:06 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 24A2535862 for ; Mon, 18 Apr 2022 12:21:26 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id B128B60EFC for ; Mon, 18 Apr 2022 19:21:25 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 86A1AC385AA; Mon, 18 Apr 2022 19:21:23 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1650309685; bh=eckoXJzmBTI4aVkvgbMnauXFMVFr4QIUnB1ojLDGags=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=IvZ9E+WlsjRmyP8mtaK22IwRbkzPaEiIMPpHbsT9D8gYpywzPMGKqu50ZMj2IRbi2 1rtQx1NAhjk6/4V2qLbNLOClWXpDJk1wU3x3mMDpmJ3wr1t9/FCWeq8IJ0dLeB5UlW kjqpTZo1AfLiHStVn0rYDR6H5c6HjdhaB9GdH7wT/OMPLp5APHVt6PkfD4/4W0/I67 YYVqaDl4NgrPSltIZIbPKVyX6j2VO7jveeJRPJXO+nCoDAmvx4n4pgkSNOpxiRvAMg lEO8VdxKUg0zSRwyeoqxdPBOQTqPwc9AELWfN/cw+gcgq5PQHW0MORZrvTn3mrQ6Ko rwunCGfI9SBdA== From: Jonathan Cameron To: linux-iio@vger.kernel.org Cc: Michael Hennerich , Lars-Peter Clausen , Vincent Whitchurch , Jonathan Cameron Subject: [PATCH 08/17] staging: iio: cdc: ad7746: Break up use of chan->address and use FIELD_PREP etc Date: Mon, 18 Apr 2022 20:28:58 +0100 Message-Id: <20220418192907.763933-9-jic23@kernel.org> X-Mailer: git-send-email 2.35.3 In-Reply-To: <20220418192907.763933-1-jic23@kernel.org> References: <20220418192907.763933-1-jic23@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org From: Jonathan Cameron Instead of encoding several different fields into chan->address use an indirection to a separate per channel structure where the various fields can be expressed in a more readable form. This also allows the register values to be constructed at runtime using FIELD_PREP() Drop the now redundant _SHIFT macros. Signed-off-by: Jonathan Cameron --- drivers/staging/iio/cdc/ad7746.c | 152 ++++++++++++++++++++----------- 1 file changed, 99 insertions(+), 53 deletions(-) diff --git a/drivers/staging/iio/cdc/ad7746.c b/drivers/staging/iio/cdc/ad7746.c index 34e19677d1fe..bbb7b7db48a2 100644 --- a/drivers/staging/iio/cdc/ad7746.c +++ b/drivers/staging/iio/cdc/ad7746.c @@ -5,6 +5,7 @@ * Copyright 2011 Analog Devices Inc. */ +#include #include #include #include @@ -48,11 +49,12 @@ #define AD7746_CAPSETUP_CACHOP BIT(0) /* Voltage/Temperature Setup Register Bit Designations (AD7746_REG_VT_SETUP) */ -#define AD7746_VTSETUP_VTEN (1 << 7) -#define AD7746_VTSETUP_VTMD_INT_TEMP (0 << 5) -#define AD7746_VTSETUP_VTMD_EXT_TEMP (1 << 5) -#define AD7746_VTSETUP_VTMD_VDD_MON (2 << 5) -#define AD7746_VTSETUP_VTMD_EXT_VIN (3 << 5) +#define AD7746_VTSETUP_VTEN BIT(7) +#define AD7746_VTSETUP_VTMD_MASK GENMASK(6, 5) +#define AD7746_VTSETUP_VTMD_INT_TEMP 0 +#define AD7746_VTSETUP_VTMD_EXT_TEMP 1 +#define AD7746_VTSETUP_VTMD_VDD_MON 2 +#define AD7746_VTSETUP_VTMD_EXT_VIN 3 #define AD7746_VTSETUP_EXTREF BIT(4) #define AD7746_VTSETUP_VTSHORT BIT(1) #define AD7746_VTSETUP_VTCHOP BIT(0) @@ -64,23 +66,22 @@ #define AD7746_EXCSETUP_NEXCB BIT(4) #define AD7746_EXCSETUP_EXCA BIT(3) #define AD7746_EXCSETUP_NEXCA BIT(2) -#define AD7746_EXCSETUP_EXCLVL(x) (((x) & 0x3) << 0) +#define AD7746_EXCSETUP_EXCLVL_MASK GENMASK(1, 0) /* Config Register Bit Designations (AD7746_REG_CFG) */ -#define AD7746_CONF_VTFS_SHIFT 6 -#define AD7746_CONF_CAPFS_SHIFT 3 #define AD7746_CONF_VTFS_MASK GENMASK(7, 6) #define AD7746_CONF_CAPFS_MASK GENMASK(5, 3) -#define AD7746_CONF_MODE_IDLE (0 << 0) -#define AD7746_CONF_MODE_CONT_CONV (1 << 0) -#define AD7746_CONF_MODE_SINGLE_CONV (2 << 0) -#define AD7746_CONF_MODE_PWRDN (3 << 0) -#define AD7746_CONF_MODE_OFFS_CAL (5 << 0) -#define AD7746_CONF_MODE_GAIN_CAL (6 << 0) +#define AD7746_CONF_MODE_MASK GENMASK(2, 0) +#define AD7746_CONF_MODE_IDLE 0 +#define AD7746_CONF_MODE_CONT_CONV 1 +#define AD7746_CONF_MODE_SINGLE_CONV 2 +#define AD7746_CONF_MODE_PWRDN 3 +#define AD7746_CONF_MODE_OFFS_CAL 5 +#define AD7746_CONF_MODE_GAIN_CAL 6 /* CAPDAC Register Bit Designations (AD7746_REG_CAPDACx) */ #define AD7746_CAPDAC_DACEN BIT(7) -#define AD7746_CAPDAC_DACP(x) ((x) & 0x7F) +#define AD7746_CAPDAC_DACP_MASK 0x7F struct ad7746_chip_info { struct i2c_client *client; @@ -107,6 +108,52 @@ enum ad7746_chan { CIN2_DIFF, }; +struct ad7746_chan_info { + u8 addr; + union { + u8 vtmd; + struct { /* CAP SETUP fields */ + unsigned int cin2 : 1; + unsigned int capdiff : 1; + }; + }; +}; + +static const struct ad7746_chan_info ad7746_chan_info[] = { + [VIN] = { + .addr = AD7746_REG_VT_DATA_HIGH, + .vtmd = AD7746_VTSETUP_VTMD_EXT_VIN, + }, + [VIN_VDD] = { + .addr = AD7746_REG_VT_DATA_HIGH, + .vtmd = AD7746_VTSETUP_VTMD_VDD_MON, + }, + [TEMP_INT] = { + .addr = AD7746_REG_VT_DATA_HIGH, + .vtmd = AD7746_VTSETUP_VTMD_INT_TEMP, + }, + [TEMP_EXT] = { + .addr = AD7746_REG_VT_DATA_HIGH, + .vtmd = AD7746_VTSETUP_VTMD_EXT_TEMP, + }, + [CIN1] = { + .addr = AD7746_REG_CAP_DATA_HIGH, + }, + [CIN1_DIFF] = { + .addr = AD7746_REG_CAP_DATA_HIGH, + .capdiff = 1, + }, + [CIN2] = { + .addr = AD7746_REG_CAP_DATA_HIGH, + .cin2 = 1, + }, + [CIN2_DIFF] = { + .addr = AD7746_REG_CAP_DATA_HIGH, + .cin2 = 1, + .capdiff = 1, + }, +}; + static const struct iio_chan_spec ad7746_channels[] = { [VIN] = { .type = IIO_VOLTAGE, @@ -114,8 +161,7 @@ static const struct iio_chan_spec ad7746_channels[] = { .channel = 0, .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ), - .address = AD7746_REG_VT_DATA_HIGH << 8 | - AD7746_VTSETUP_VTMD_EXT_VIN, + .address = VIN, }, [VIN_VDD] = { .type = IIO_VOLTAGE, @@ -124,24 +170,21 @@ static const struct iio_chan_spec ad7746_channels[] = { .extend_name = "supply", .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ), - .address = AD7746_REG_VT_DATA_HIGH << 8 | - AD7746_VTSETUP_VTMD_VDD_MON, + .address = VIN_VDD, }, [TEMP_INT] = { .type = IIO_TEMP, .indexed = 1, .channel = 0, .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), - .address = AD7746_REG_VT_DATA_HIGH << 8 | - AD7746_VTSETUP_VTMD_INT_TEMP, + .address = TEMP_INT, }, [TEMP_EXT] = { .type = IIO_TEMP, .indexed = 1, .channel = 1, .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), - .address = AD7746_REG_VT_DATA_HIGH << 8 | - AD7746_VTSETUP_VTMD_EXT_TEMP, + .address = TEMP_EXT, }, [CIN1] = { .type = IIO_CAPACITANCE, @@ -151,7 +194,7 @@ static const struct iio_chan_spec ad7746_channels[] = { BIT(IIO_CHAN_INFO_CALIBSCALE) | BIT(IIO_CHAN_INFO_OFFSET), .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_SAMP_FREQ), - .address = AD7746_REG_CAP_DATA_HIGH << 8, + .address = CIN1, }, [CIN1_DIFF] = { .type = IIO_CAPACITANCE, @@ -163,8 +206,7 @@ static const struct iio_chan_spec ad7746_channels[] = { BIT(IIO_CHAN_INFO_CALIBSCALE) | BIT(IIO_CHAN_INFO_OFFSET), .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_SAMP_FREQ), - .address = AD7746_REG_CAP_DATA_HIGH << 8 | - AD7746_CAPSETUP_CAPDIFF + .address = CIN1_DIFF, }, [CIN2] = { .type = IIO_CAPACITANCE, @@ -174,8 +216,7 @@ static const struct iio_chan_spec ad7746_channels[] = { BIT(IIO_CHAN_INFO_CALIBSCALE) | BIT(IIO_CHAN_INFO_OFFSET), .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_SAMP_FREQ), - .address = AD7746_REG_CAP_DATA_HIGH << 8 | - AD7746_CAPSETUP_CIN2, + .address = CIN2, }, [CIN2_DIFF] = { .type = IIO_CAPACITANCE, @@ -187,8 +228,7 @@ static const struct iio_chan_spec ad7746_channels[] = { BIT(IIO_CHAN_INFO_CALIBSCALE) | BIT(IIO_CHAN_INFO_OFFSET), .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_SAMP_FREQ), - .address = AD7746_REG_CAP_DATA_HIGH << 8 | - AD7746_CAPSETUP_CAPDIFF | AD7746_CAPSETUP_CIN2, + .address = CIN2_DIFF, } }; @@ -224,10 +264,13 @@ static int ad7746_select_channel(struct iio_dev *indio_dev, switch (chan->type) { case IIO_CAPACITANCE: - cap_setup = (chan->address & 0xFF) | AD7746_CAPSETUP_CAPEN; + cap_setup = FIELD_PREP(AD7746_CAPSETUP_CIN2, + ad7746_chan_info[chan->address].cin2) | + FIELD_PREP(AD7746_CAPSETUP_CAPDIFF, + ad7746_chan_info[chan->address].capdiff) | + FIELD_PREP(AD7746_CAPSETUP_CAPEN, 1); vt_setup = chip->vt_setup & ~AD7746_VTSETUP_VTEN; - idx = (chip->config & AD7746_CONF_CAPFS_MASK) >> - AD7746_CONF_CAPFS_SHIFT; + idx = FIELD_GET(AD7746_CONF_CAPFS_MASK, chip->config); delay = ad7746_cap_filter_rate_table[idx][1]; ret = ad7746_set_capdac(chip, chan->channel); @@ -239,10 +282,11 @@ static int ad7746_select_channel(struct iio_dev *indio_dev, break; case IIO_VOLTAGE: case IIO_TEMP: - vt_setup = (chan->address & 0xFF) | AD7746_VTSETUP_VTEN; + vt_setup = FIELD_PREP(AD7746_VTSETUP_VTMD_MASK, + ad7746_chan_info[chan->address].vtmd) | + FIELD_PREP(AD7746_VTSETUP_VTEN, 1); cap_setup = chip->cap_setup & ~AD7746_CAPSETUP_CAPEN; - idx = (chip->config & AD7746_CONF_VTFS_MASK) >> - AD7746_CONF_VTFS_SHIFT; + idx = FIELD_GET(AD7746_CONF_VTFS_MASK, chip->config); delay = ad7746_cap_filter_rate_table[idx][1]; break; default: @@ -325,7 +369,8 @@ static ssize_t ad7746_start_offset_calib(struct device *dev, return ret; return ad7746_start_calib(dev, attr, buf, len, - AD7746_CONF_MODE_OFFS_CAL); + FIELD_PREP(AD7746_CONF_MODE_MASK, + AD7746_CONF_MODE_OFFS_CAL)); } static ssize_t ad7746_start_gain_calib(struct device *dev, @@ -340,7 +385,8 @@ static ssize_t ad7746_start_gain_calib(struct device *dev, return ret; return ad7746_start_calib(dev, attr, buf, len, - AD7746_CONF_MODE_GAIN_CAL); + FIELD_PREP(AD7746_CONF_MODE_MASK, + AD7746_CONF_MODE_GAIN_CAL)); } static IIO_DEVICE_ATTR(in_capacitance0_calibbias_calibration, @@ -367,7 +413,7 @@ static int ad7746_store_cap_filter_rate_setup(struct ad7746_chip_info *chip, i = ARRAY_SIZE(ad7746_cap_filter_rate_table) - 1; chip->config &= ~AD7746_CONF_CAPFS_MASK; - chip->config |= i << AD7746_CONF_CAPFS_SHIFT; + chip->config |= FIELD_PREP(AD7746_CONF_CAPFS_MASK, i); return 0; } @@ -385,7 +431,7 @@ static int ad7746_store_vt_filter_rate_setup(struct ad7746_chip_info *chip, i = ARRAY_SIZE(ad7746_vt_filter_rate_table) - 1; chip->config &= ~AD7746_CONF_VTFS_MASK; - chip->config |= i << AD7746_CONF_VTFS_SHIFT; + chip->config |= FIELD_PREP(AD7746_CONF_VTFS_MASK, i); return 0; } @@ -468,7 +514,7 @@ static int ad7746_write_raw(struct iio_dev *indio_dev, val /= 338646; mutex_lock(&chip->lock); chip->capdac[chan->channel][chan->differential] = val > 0 ? - AD7746_CAPDAC_DACP(val) | AD7746_CAPDAC_DACEN : 0; + FIELD_PREP(AD7746_CAPDAC_DACP_MASK, val) | AD7746_CAPDAC_DACEN : 0; ret = ad7746_set_capdac(chip, chan->channel); if (ret < 0) { @@ -517,14 +563,16 @@ static int ad7746_read_channel(struct iio_dev *indio_dev, return ret; delay = ret; - regval = chip->config | AD7746_CONF_MODE_SINGLE_CONV; + regval = chip->config | FIELD_PREP(AD7746_CONF_MODE_MASK, + AD7746_CONF_MODE_SINGLE_CONV); ret = i2c_smbus_write_byte_data(chip->client, AD7746_REG_CFG, regval); if (ret < 0) return ret; msleep(delay); /* Now read the actual register */ - ret = i2c_smbus_read_i2c_block_data(chip->client, chan->address >> 8, + ret = i2c_smbus_read_i2c_block_data(chip->client, + ad7746_chan_info[chan->address].addr, 3, data); if (ret < 0) return ret; @@ -598,8 +646,8 @@ static int ad7746_read_raw(struct iio_dev *indio_dev, return IIO_VAL_INT; case IIO_CHAN_INFO_OFFSET: - *val = AD7746_CAPDAC_DACP(chip->capdac[chan->channel] - [chan->differential]) * 338646; + *val = FIELD_GET(AD7746_CAPDAC_DACP_MASK, + chip->capdac[chan->channel][chan->differential]) * 338646; return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: @@ -622,13 +670,11 @@ static int ad7746_read_raw(struct iio_dev *indio_dev, case IIO_CHAN_INFO_SAMP_FREQ: switch (chan->type) { case IIO_CAPACITANCE: - idx = (chip->config & AD7746_CONF_CAPFS_MASK) >> - AD7746_CONF_CAPFS_SHIFT; + idx = FIELD_GET(AD7746_CONF_CAPFS_MASK, chip->config); *val = ad7746_cap_filter_rate_table[idx][0]; return IIO_VAL_INT; case IIO_VOLTAGE: - idx = (chip->config & AD7746_CONF_VTFS_MASK) >> - AD7746_CONF_VTFS_SHIFT; + idx = FIELD_GET(AD7746_CONF_VTFS_MASK, chip->config); *val = ad7746_vt_filter_rate_table[idx][0]; return IIO_VAL_INT; default: @@ -694,16 +740,16 @@ static int ad7746_probe(struct i2c_client *client, if (!ret) { switch (vdd_permille) { case 125: - regval |= AD7746_EXCSETUP_EXCLVL(0); + regval |= FIELD_PREP(AD7746_EXCSETUP_EXCLVL_MASK, 0); break; case 250: - regval |= AD7746_EXCSETUP_EXCLVL(1); + regval |= FIELD_PREP(AD7746_EXCSETUP_EXCLVL_MASK, 1); break; case 375: - regval |= AD7746_EXCSETUP_EXCLVL(2); + regval |= FIELD_PREP(AD7746_EXCSETUP_EXCLVL_MASK, 2); break; case 500: - regval |= AD7746_EXCSETUP_EXCLVL(3); + regval |= FIELD_PREP(AD7746_EXCSETUP_EXCLVL_MASK, 3); break; default: break; From patchwork Mon Apr 18 19:28:59 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonathan Cameron X-Patchwork-Id: 12817067 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 888C3C433FE for ; Mon, 18 Apr 2022 19:21:31 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S240785AbiDRTYJ (ORCPT ); Mon, 18 Apr 2022 15:24:09 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44614 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1347671AbiDRTYJ (ORCPT ); Mon, 18 Apr 2022 15:24:09 -0400 Received: from ams.source.kernel.org (ams.source.kernel.org [IPv6:2604:1380:4601:e00::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D6A0235A8F for ; Mon, 18 Apr 2022 12:21:29 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id 92873B81087 for ; Mon, 18 Apr 2022 19:21:28 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 92C11C385A1; Mon, 18 Apr 2022 19:21:25 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1650309687; bh=JBJI2t4VOKygfU39t9hABHDoUygqi0pLsW0/zNUrv7Y=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=pzN24LMuKdY79hJK4fhLYDGEEqpZ/qDIoQ0+lIufpzA0lGhxhXzv99KmrNeiS+00A mVxNzSvo7ikxGLzsQgRMhY/lG1cjXokwUbfX4z0kJDfy8pXJxYfY9KH4PTyvq+OmML 4fgn7dAY7uVnIyuh6xjgw2QC+fqp6Wplgfgoum6hnOd6N19icRTkFdmFLD3Io67S4T cXJkPHM4OQnPOYeU7Uyuqo8PP+5X/bFb3EOWTkMPzol2u2XK5KZxsdkkKCCMmBQYc5 KQzttLHdcsjXp0JUTe5Knm+lfdjoEAwCuQVU8YEmt78uHj31bbSsknk1YadNjDVo6P FC4tAODhveQJg== From: Jonathan Cameron To: linux-iio@vger.kernel.org Cc: Michael Hennerich , Lars-Peter Clausen , Vincent Whitchurch , Jonathan Cameron Subject: [PATCH 09/17] staging: iio: cdc: ad7746: Drop usused i2c_set_clientdata() Date: Mon, 18 Apr 2022 20:28:59 +0100 Message-Id: <20220418192907.763933-10-jic23@kernel.org> X-Mailer: git-send-email 2.35.3 In-Reply-To: <20220418192907.763933-1-jic23@kernel.org> References: <20220418192907.763933-1-jic23@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org From: Jonathan Cameron As the comment states, this was only used in remove() and now there is no explicit remove() function to make use of it. Signed-off-by: Jonathan Cameron --- drivers/staging/iio/cdc/ad7746.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/staging/iio/cdc/ad7746.c b/drivers/staging/iio/cdc/ad7746.c index bbb7b7db48a2..f6b54e817973 100644 --- a/drivers/staging/iio/cdc/ad7746.c +++ b/drivers/staging/iio/cdc/ad7746.c @@ -706,8 +706,6 @@ static int ad7746_probe(struct i2c_client *client, return -ENOMEM; chip = iio_priv(indio_dev); mutex_init(&chip->lock); - /* this is only used for device removal purposes */ - i2c_set_clientdata(client, indio_dev); chip->client = client; chip->capdac_set = -1; From patchwork Mon Apr 18 19:29:00 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonathan Cameron X-Patchwork-Id: 12817068 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3A552C433F5 for ; Mon, 18 Apr 2022 19:21:33 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1347671AbiDRTYL (ORCPT ); Mon, 18 Apr 2022 15:24:11 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44626 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1347673AbiDRTYK (ORCPT ); Mon, 18 Apr 2022 15:24:10 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [IPv6:2604:1380:4641:c500::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 973CC32EFB for ; Mon, 18 Apr 2022 12:21:30 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 2147560CA5 for ; Mon, 18 Apr 2022 19:21:30 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 27437C385AA; Mon, 18 Apr 2022 19:21:27 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1650309689; bh=4LhUjNxnDV20JV09fMrq3QtcoCSkWgs8GmlwmFFdNPs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Z9ZulbaLQrQHJUDHQ4p4zbOkyiKD/8bbF4KvChHjVYYjJ3rg1sGCKAET/WRQrVjWv b29WxShKWt5Z2Il20raM2qNHi9k/W+Y4LYXGAyqV0DeZ8mjgYezCLg2Vk8qOUkDCvk bdMCZzfNvZy+LGJJHP79AJGEKjUo4F9vp0rgjI5+FLPJpEc9Fh0otKO/jYMvFl+GGd 51xGfxBImPVfuY5pGb1W6cQcMMdydX6f+XNwkohtohS02tYD7fn9M4q+44os9UGXYA hozEE79YXNIqEgZf7vWVR1KpV/mUiO9tXWURXMlVqNUHvihsw74t+m6kMyVnG0iD4z h1GkhbFILQz0Q== From: Jonathan Cameron To: linux-iio@vger.kernel.org Cc: Michael Hennerich , Lars-Peter Clausen , Vincent Whitchurch , Jonathan Cameron Subject: [PATCH 10/17] staging: iio: cdc: ad7746: Use _raw and _scale for temperature channels. Date: Mon, 18 Apr 2022 20:29:00 +0100 Message-Id: <20220418192907.763933-11-jic23@kernel.org> X-Mailer: git-send-email 2.35.3 In-Reply-To: <20220418192907.763933-1-jic23@kernel.org> References: <20220418192907.763933-1-jic23@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org From: Jonathan Cameron Performing the maths to rescale a 24 bit raw reading within the driver was resulting in precision losses. So make that userspace's problem by exporting the scale and letting the maths be done in userspace with appropriate precision. Issue identified using roadtester testing framework. Signed-off-by: Jonathan Cameron --- drivers/staging/iio/cdc/ad7746.c | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/drivers/staging/iio/cdc/ad7746.c b/drivers/staging/iio/cdc/ad7746.c index f6b54e817973..0dc5630d0655 100644 --- a/drivers/staging/iio/cdc/ad7746.c +++ b/drivers/staging/iio/cdc/ad7746.c @@ -176,14 +176,16 @@ static const struct iio_chan_spec ad7746_channels[] = { .type = IIO_TEMP, .indexed = 1, .channel = 0, - .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), .address = TEMP_INT, }, [TEMP_EXT] = { .type = IIO_TEMP, .indexed = 1, .channel = 1, - .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), .address = TEMP_EXT, }, [CIN1] = { @@ -579,18 +581,6 @@ static int ad7746_read_channel(struct iio_dev *indio_dev, *val = get_unaligned_be24(data) - 0x800000; - switch (chan->type) { - case IIO_TEMP: - /* - * temperature in milli degrees Celsius - * T = ((*val / 2048) - 4096) * 1000 - */ - *val = (*val * 125) / 256; - break; - default: - break; - } - return 0; } @@ -605,7 +595,6 @@ static int ad7746_read_raw(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_RAW: - case IIO_CHAN_INFO_PROCESSED: mutex_lock(&chip->lock); ret = ad7746_read_channel(indio_dev, chan, val); mutex_unlock(&chip->lock); @@ -664,6 +653,10 @@ static int ad7746_read_raw(struct iio_dev *indio_dev, *val *= 6; *val2 = 23; return IIO_VAL_FRACTIONAL_LOG2; + case IIO_TEMP: + *val = 125; + *val2 = 8; + return IIO_VAL_FRACTIONAL_LOG2; default: return -EINVAL; } From patchwork Mon Apr 18 19:29:01 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonathan Cameron X-Patchwork-Id: 12817069 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2A4E8C433F5 for ; Mon, 18 Apr 2022 19:21:37 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1347673AbiDRTYP (ORCPT ); Mon, 18 Apr 2022 15:24:15 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44692 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1347674AbiDRTYN (ORCPT ); Mon, 18 Apr 2022 15:24:13 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [IPv6:2604:1380:4641:c500::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7E1EE3586E for ; Mon, 18 Apr 2022 12:21:32 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 45D3760E0A for ; Mon, 18 Apr 2022 19:21:32 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 00905C385A7; Mon, 18 Apr 2022 19:21:29 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1650309691; bh=BDpIENFNuMlesggVJDYLo8PfT0a4928SawiqYoWIxFI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=VqOr4+nKp+eIWxq8VYxYTKbPDeaX6Ig5ZMCHOd3AiXZCfw1kUXOqsTWgrWeBHByAq PMhO3BjFQfv9fHvI3+g66GTvRvmpjbeG7VYZNR/7mYk1BjypRC23lXPxX8eqvZAGY5 KhEoSt/+x7EYAH7azsUoAWoyn5r7ODrtmTpfFx9nZ8yhvop2m0KAI64ADFIcYL+Wx0 mYsq/VbN+/jiH1xqaHtxPxKk7uqQqslM7PB8jZXAQ8hcs1e7qlLyIxOYDTywq7Pp69 z2h1YU878V/syAtCsKG9A0u/9WuRqzuIZVoVF5EvgFdxKkOCyft894n6Anz73K/C2w 9HHm8iDmgPBCA== From: Jonathan Cameron To: linux-iio@vger.kernel.org Cc: Michael Hennerich , Lars-Peter Clausen , Vincent Whitchurch , Jonathan Cameron Subject: [PATCH 11/17] iio: core: Introduce _inputoffset for differential channels Date: Mon, 18 Apr 2022 20:29:01 +0100 Message-Id: <20220418192907.763933-12-jic23@kernel.org> X-Mailer: git-send-email 2.35.3 In-Reply-To: <20220418192907.763933-1-jic23@kernel.org> References: <20220418192907.763933-1-jic23@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org From: Jonathan Cameron Address an ABI gap for device where the offset of both lines in a differential pair may be controlled so as to allow a wider range of inputs, but without having any direct effect of the differential measurement. _offset cannot be used as to remain in line with existing usage, userspace would be expected to apply it as (_raw + _offset) * scale whereas _inputoffset is not. Similarly calibbias is expected to tweak the measurement seen, not the adjust the two lines of the differential pair. Needed for in_capacitanceX-capacitanceY_inputoffset for the AD7746 CDC driver. Signed-off-by: Jonathan Cameron --- I''m not entirely happy with the naming on this one, so if anyone has a better idea I'm definitely open to it! --- Documentation/ABI/testing/sysfs-bus-iio | 13 +++++++++++++ drivers/iio/industrialio-core.c | 1 + include/linux/iio/types.h | 1 + 3 files changed, 15 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio index b19ff517e5d6..4fbb5a257ef5 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio +++ b/Documentation/ABI/testing/sysfs-bus-iio @@ -199,6 +199,19 @@ Description: is required is a consistent labeling. Units after application of scale and offset are nanofarads. +What: /sys/.../iio:deviceX/in_capacitableY-capacitanceZ_inputoffset +KernelVersion: 5.19 +Contact: linux-iio@vger.kernel.org +Description: + For differential channels, this an offset that is applied + equally to both inputs. As the reading is of the difference + between the two inputs this should not be applied to the _raw + reading by userspace (unlike _offset) and unlike calibbias + it does not affect the differential value measured because + the effect of _inputoffset cancels out across the two inputs + that make up the differential pair. It is expressed with + the same scaling as _raw. + What: /sys/bus/iio/devices/iio:deviceX/in_temp_raw What: /sys/bus/iio/devices/iio:deviceX/in_tempX_raw What: /sys/bus/iio/devices/iio:deviceX/in_temp_x_raw diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index d831835770da..8aebef08ca1d 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -168,6 +168,7 @@ static const char * const iio_chan_info_postfix[] = { [IIO_CHAN_INFO_OVERSAMPLING_RATIO] = "oversampling_ratio", [IIO_CHAN_INFO_THERMOCOUPLE_TYPE] = "thermocouple_type", [IIO_CHAN_INFO_CALIBAMBIENT] = "calibambient", + [IIO_CHAN_INFO_INPUTOFFSET] = "inputoffset", }; /** * iio_device_id() - query the unique ID for the device diff --git a/include/linux/iio/types.h b/include/linux/iio/types.h index a7aa91f3a8dc..c7f79a251a14 100644 --- a/include/linux/iio/types.h +++ b/include/linux/iio/types.h @@ -63,6 +63,7 @@ enum iio_chan_info_enum { IIO_CHAN_INFO_OVERSAMPLING_RATIO, IIO_CHAN_INFO_THERMOCOUPLE_TYPE, IIO_CHAN_INFO_CALIBAMBIENT, + IIO_CHAN_INFO_INPUTOFFSET, }; #endif /* _IIO_TYPES_H_ */ From patchwork Mon Apr 18 19:29:02 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonathan Cameron X-Patchwork-Id: 12817070 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id A136AC433EF for ; Mon, 18 Apr 2022 19:21:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S244753AbiDRTYR (ORCPT ); Mon, 18 Apr 2022 15:24:17 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44742 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1347675AbiDRTYQ (ORCPT ); Mon, 18 Apr 2022 15:24:16 -0400 Received: from ams.source.kernel.org (ams.source.kernel.org [145.40.68.75]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 09F8332EFB for ; Mon, 18 Apr 2022 12:21:36 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id A5F7FB8105F for ; Mon, 18 Apr 2022 19:21:34 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 257A5C385AA; Mon, 18 Apr 2022 19:21:31 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1650309693; bh=okgAGAVfOgUl0WQ4R6oaY0E01YBenpl9Y5vuhP4A9P4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Wa2EYEijRWd/dKccx9LpB3H6dHjxHZu5WRw4YwNuvXj3+nnbaveMLlFbvKDppL75N DxtRCsPyRPCPWxBbEyxX+X2d/yc7bvi66Rnt1bOvJ3nz9Zdn/U//h870V0+vR9gV2a 8AGD3kO+GKmjSe4LtXg2m1I6vzoKLVL9k4W5RGiEKsZUTmU/zdv858FOlrSs6fY3jU Eat24clzBAjjjetGT8azkQ+pKP53f/MuQSE9YkSLvEi8PzPlEXBE5Wh2hS75XvWise yP3zsPdVgWEXOXLqigC5lHA+cIg5oSIJuhtkFYQJQQHs2u7/F7HizQjVQq0zQAMhPr xuyeLPNuLOLvA== From: Jonathan Cameron To: linux-iio@vger.kernel.org Cc: Michael Hennerich , Lars-Peter Clausen , Vincent Whitchurch , Jonathan Cameron Subject: [PATCH 12/17] staging: iio: cdc: ad7746: Switch from _offset to _inputoffset for differential channels. Date: Mon, 18 Apr 2022 20:29:02 +0100 Message-Id: <20220418192907.763933-13-jic23@kernel.org> X-Mailer: git-send-email 2.35.3 In-Reply-To: <20220418192907.763933-1-jic23@kernel.org> References: <20220418192907.763933-1-jic23@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org From: Jonathan Cameron As this offset is applied equally to both lines of the differential pair, _ofset should not be used. Use the new ABI _inputoffset instead to avoid userspace software applying this value when calculating real value = (_raw + _offset) * _scale Also add a comment to explain why an offset of 0x800000 is applied within the driver rather than exposed to userspace. Signed-off-by: Jonathan Cameron --- drivers/staging/iio/cdc/ad7746.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/staging/iio/cdc/ad7746.c b/drivers/staging/iio/cdc/ad7746.c index 0dc5630d0655..46cdddab495f 100644 --- a/drivers/staging/iio/cdc/ad7746.c +++ b/drivers/staging/iio/cdc/ad7746.c @@ -205,7 +205,7 @@ static const struct iio_chan_spec ad7746_channels[] = { .channel = 0, .channel2 = 2, .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | - BIT(IIO_CHAN_INFO_CALIBSCALE) | BIT(IIO_CHAN_INFO_OFFSET), + BIT(IIO_CHAN_INFO_CALIBSCALE) | BIT(IIO_CHAN_INFO_INPUTOFFSET), .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_SAMP_FREQ), .address = CIN1_DIFF, @@ -227,7 +227,7 @@ static const struct iio_chan_spec ad7746_channels[] = { .channel = 1, .channel2 = 3, .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | - BIT(IIO_CHAN_INFO_CALIBSCALE) | BIT(IIO_CHAN_INFO_OFFSET), + BIT(IIO_CHAN_INFO_CALIBSCALE) | BIT(IIO_CHAN_INFO_INPUTOFFSET), .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_SAMP_FREQ), .address = CIN2_DIFF, @@ -504,6 +504,7 @@ static int ad7746_write_raw(struct iio_dev *indio_dev, return 0; case IIO_CHAN_INFO_OFFSET: + case IIO_CHAN_INFO_INPUTOFFSET: if (val < 0 || val > 43008000) /* 21pF */ return -EINVAL; @@ -579,6 +580,10 @@ static int ad7746_read_channel(struct iio_dev *indio_dev, if (ret < 0) return ret; + /* + * Offset applied internally becaue the _offset userspace interface is + * needed for the CAP DACs which apply a controllable offset. + */ *val = get_unaligned_be24(data) - 0x800000; return 0; @@ -635,6 +640,7 @@ static int ad7746_read_raw(struct iio_dev *indio_dev, return IIO_VAL_INT; case IIO_CHAN_INFO_OFFSET: + case IIO_CHAN_INFO_INPUTOFFSET: *val = FIELD_GET(AD7746_CAPDAC_DACP_MASK, chip->capdac[chan->channel][chan->differential]) * 338646; From patchwork Mon Apr 18 19:29:03 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonathan Cameron X-Patchwork-Id: 12817072 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 61F10C433F5 for ; Mon, 18 Apr 2022 19:21:41 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1347674AbiDRTYS (ORCPT ); Mon, 18 Apr 2022 15:24:18 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44762 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S243181AbiDRTYS (ORCPT ); Mon, 18 Apr 2022 15:24:18 -0400 Received: from ams.source.kernel.org (ams.source.kernel.org [IPv6:2604:1380:4601:e00::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8971235862 for ; Mon, 18 Apr 2022 12:21:37 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id 47BF5B8108E for ; Mon, 18 Apr 2022 19:21:36 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id CD4F0C385A1; Mon, 18 Apr 2022 19:21:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1650309695; bh=0aZlaNHVqsKqlVWGe8WBUFWTAjkEzfYtXa79EvUXAkY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=gWsW8z8+xiYMc5KdD291qJoZQlyEvqlM8znnkjVC8uSeba77NLdLn05a8Mk1fq9V0 rtIVxey+baD9DPS6NnKKXjIzPKP9/AwUm6DMiThRkV4SMo5Px1R+mgjh6J4Ft8oNwv ciyq5UfBVL1XWvG4w7jGjPLlw8U45e5VJ91O2QAnC0uOdmB/AtG5UflJLUFjhSCo/c qperPQaUmbz1Pjk83y186F/TiCEaiDVc4Pny7Zaxtpcdz4VFzOEMBX+nby038MQsIC uAYvoaRO0AYmKDXT9LnQC3XPbpRqUza9oDnJ6k9L+4qViBBWAOdRBiuglihC/OFQmM 4omZL6e5wRvyA== From: Jonathan Cameron To: linux-iio@vger.kernel.org Cc: Michael Hennerich , Lars-Peter Clausen , Vincent Whitchurch , Jonathan Cameron Subject: [PATCH 13/17] staging: iio: cdc: ad7746: Use read_avail() rather than opencoding. Date: Mon, 18 Apr 2022 20:29:03 +0100 Message-Id: <20220418192907.763933-14-jic23@kernel.org> X-Mailer: git-send-email 2.35.3 In-Reply-To: <20220418192907.763933-1-jic23@kernel.org> References: <20220418192907.763933-1-jic23@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org From: Jonathan Cameron Switch over to the IIO core handling for _available attributes making them available for in kernel users and enforcing correct naming etc automatically. Signed-off-by: Jonathan Cameron --- drivers/staging/iio/cdc/ad7746.c | 39 +++++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/drivers/staging/iio/cdc/ad7746.c b/drivers/staging/iio/cdc/ad7746.c index 46cdddab495f..6fe3221c8ace 100644 --- a/drivers/staging/iio/cdc/ad7746.c +++ b/drivers/staging/iio/cdc/ad7746.c @@ -161,6 +161,7 @@ static const struct iio_chan_spec ad7746_channels[] = { .channel = 0, .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ), + .info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_SAMP_FREQ), .address = VIN, }, [VIN_VDD] = { @@ -170,6 +171,7 @@ static const struct iio_chan_spec ad7746_channels[] = { .extend_name = "supply", .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ), + .info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_SAMP_FREQ), .address = VIN_VDD, }, [TEMP_INT] = { @@ -196,6 +198,7 @@ static const struct iio_chan_spec ad7746_channels[] = { BIT(IIO_CHAN_INFO_CALIBSCALE) | BIT(IIO_CHAN_INFO_OFFSET), .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_SAMP_FREQ), + .info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_SAMP_FREQ), .address = CIN1, }, [CIN1_DIFF] = { @@ -208,6 +211,7 @@ static const struct iio_chan_spec ad7746_channels[] = { BIT(IIO_CHAN_INFO_CALIBSCALE) | BIT(IIO_CHAN_INFO_INPUTOFFSET), .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_SAMP_FREQ), + .info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_SAMP_FREQ), .address = CIN1_DIFF, }, [CIN2] = { @@ -218,6 +222,7 @@ static const struct iio_chan_spec ad7746_channels[] = { BIT(IIO_CHAN_INFO_CALIBSCALE) | BIT(IIO_CHAN_INFO_OFFSET), .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_SAMP_FREQ), + .info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_SAMP_FREQ), .address = CIN2, }, [CIN2_DIFF] = { @@ -230,6 +235,7 @@ static const struct iio_chan_spec ad7746_channels[] = { BIT(IIO_CHAN_INFO_CALIBSCALE) | BIT(IIO_CHAN_INFO_INPUTOFFSET), .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_SAMP_FREQ), + .info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_SAMP_FREQ), .address = CIN2_DIFF, } }; @@ -438,18 +444,12 @@ static int ad7746_store_vt_filter_rate_setup(struct ad7746_chip_info *chip, return 0; } -static IIO_CONST_ATTR(in_voltage_sampling_frequency_available, "50 31 16 8"); -static IIO_CONST_ATTR(in_capacitance_sampling_frequency_available, - "91 84 50 26 16 13 11 9"); - static struct attribute *ad7746_attributes[] = { &iio_dev_attr_in_capacitance0_calibbias_calibration.dev_attr.attr, &iio_dev_attr_in_capacitance0_calibscale_calibration.dev_attr.attr, &iio_dev_attr_in_capacitance1_calibscale_calibration.dev_attr.attr, &iio_dev_attr_in_capacitance1_calibbias_calibration.dev_attr.attr, &iio_dev_attr_in_voltage0_calibscale_calibration.dev_attr.attr, - &iio_const_attr_in_voltage_sampling_frequency_available.dev_attr.attr, - &iio_const_attr_in_capacitance_sampling_frequency_available.dev_attr.attr, NULL, }; @@ -552,6 +552,32 @@ static int ad7746_write_raw(struct iio_dev *indio_dev, } } +static const int ad7746_v_samp_freq[] = { 50, 31, 16, 8, }; +static const int ad7746_cap_samp_freq[] = { 91, 84, 50, 26, 16, 13, 11, 9, }; + +static int ad7746_read_avail(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, const int **vals, + int *type, int *length, long mask) +{ + if (mask != IIO_CHAN_INFO_SAMP_FREQ) + return -EINVAL; + + switch (chan->type) { + case IIO_VOLTAGE: + *vals = ad7746_v_samp_freq; + *length = ARRAY_SIZE(ad7746_v_samp_freq); + break; + case IIO_CAPACITANCE: + *vals = ad7746_cap_samp_freq; + *length = ARRAY_SIZE(ad7746_cap_samp_freq); + break; + default: + return -EINVAL; + } + *type = IIO_VAL_INT; + return IIO_AVAIL_LIST; +} + static int ad7746_read_channel(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val) @@ -687,6 +713,7 @@ static int ad7746_read_raw(struct iio_dev *indio_dev, static const struct iio_info ad7746_info = { .attrs = &ad7746_attribute_group, .read_raw = ad7746_read_raw, + .read_avail = ad7746_read_avail, .write_raw = ad7746_write_raw, }; From patchwork Mon Apr 18 19:29:04 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonathan Cameron X-Patchwork-Id: 12817071 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id B53DEC433FE for ; Mon, 18 Apr 2022 19:21:39 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S244967AbiDRTYR (ORCPT ); Mon, 18 Apr 2022 15:24:17 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44758 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1347675AbiDRTYR (ORCPT ); Mon, 18 Apr 2022 15:24:17 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id BB23035A80 for ; Mon, 18 Apr 2022 12:21:37 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 4A90760E16 for ; Mon, 18 Apr 2022 19:21:37 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 7A123C385A7; Mon, 18 Apr 2022 19:21:35 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1650309696; bh=EjO9q3akkN+aIPxTyZeloHCvdZ06XlTfElMKLOn/fIQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=rDSPCJBqJJ6S25Lz6fpIgJzetAgIo2cXwU50xBU8tHSP+0brPLOqe98Ol19TTCchC qboEAD5VvkqooYB6cYumno3IazqD/ewQ4AVZaJA0C/5v0BON+FdNxjOXCRvBVErG7v II4CpHEhLsuDZKZfuFdBIW7eBgASQTkMdVcD2ir0M/UjX2/ef+Pdq0/PBSYoPnoeRG 3DIcDLwpVDHB3gQjK+K8Q6m/BAIThV3CbpWTOQAwIkIabp/9FhEI9Hy37T1aQLNL7p hJ7z2S9k/hoqjgzVnoGfTjlBfsW9q+AoGUdBgHVWBACwhYaRWrwmZ1UdlOT3Gh1WDy nz1rbgWa/ZNeg== From: Jonathan Cameron To: linux-iio@vger.kernel.org Cc: Michael Hennerich , Lars-Peter Clausen , Vincent Whitchurch , Jonathan Cameron Subject: [PATCH 14/17] staging: iio: ad7746: White space cleanup Date: Mon, 18 Apr 2022 20:29:04 +0100 Message-Id: <20220418192907.763933-15-jic23@kernel.org> X-Mailer: git-send-email 2.35.3 In-Reply-To: <20220418192907.763933-1-jic23@kernel.org> References: <20220418192907.763933-1-jic23@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org From: Jonathan Cameron Tidy up some trivial whitespace issues. Signed-off-by: Jonathan Cameron --- drivers/staging/iio/cdc/ad7746.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/drivers/staging/iio/cdc/ad7746.c b/drivers/staging/iio/cdc/ad7746.c index 6fe3221c8ace..058f1b74122e 100644 --- a/drivers/staging/iio/cdc/ad7746.c +++ b/drivers/staging/iio/cdc/ad7746.c @@ -19,9 +19,7 @@ #include #include -/* - * AD7746 Register Definition - */ +/* AD7746 Register Definition */ #define AD7746_REG_STATUS 0 #define AD7746_REG_CAP_DATA_HIGH 1 @@ -242,12 +240,12 @@ static const struct iio_chan_spec ad7746_channels[] = { /* Values are Update Rate (Hz), Conversion Time (ms) + 1*/ static const unsigned char ad7746_vt_filter_rate_table[][2] = { - {50, 20 + 1}, {31, 32 + 1}, {16, 62 + 1}, {8, 122 + 1}, + { 50, 20 + 1 }, { 31, 32 + 1 }, { 16, 62 + 1 }, { 8, 122 + 1 }, }; static const unsigned char ad7746_cap_filter_rate_table[][2] = { - {91, 11 + 1}, {84, 12 + 1}, {50, 20 + 1}, {26, 38 + 1}, - {16, 62 + 1}, {13, 77 + 1}, {11, 92 + 1}, {9, 110 + 1}, + { 91, 11 + 1 }, { 84, 12 + 1 }, { 50, 20 + 1 }, { 26, 38 + 1 }, + { 16, 62 + 1 }, { 13, 77 + 1 }, { 11, 92 + 1 }, { 9, 110 + 1 }, }; static int ad7746_set_capdac(struct ad7746_chip_info *chip, int channel) @@ -730,6 +728,7 @@ static int ad7746_probe(struct i2c_client *client, indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*chip)); if (!indio_dev) return -ENOMEM; + chip = iio_priv(indio_dev); mutex_init(&chip->lock); @@ -780,8 +779,8 @@ static int ad7746_probe(struct i2c_client *client, } } - ret = i2c_smbus_write_byte_data(chip->client, - AD7746_REG_EXC_SETUP, regval); + ret = i2c_smbus_write_byte_data(chip->client, AD7746_REG_EXC_SETUP, + regval); if (ret < 0) return ret; @@ -794,7 +793,6 @@ static const struct i2c_device_id ad7746_id[] = { { "ad7747", 7747 }, {} }; - MODULE_DEVICE_TABLE(i2c, ad7746_id); static const struct of_device_id ad7746_of_match[] = { @@ -803,7 +801,6 @@ static const struct of_device_id ad7746_of_match[] = { { .compatible = "adi,ad7747" }, { }, }; - MODULE_DEVICE_TABLE(of, ad7746_of_match); static struct i2c_driver ad7746_driver = { From patchwork Mon Apr 18 19:29:05 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonathan Cameron X-Patchwork-Id: 12817073 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 063F5C4332F for ; Mon, 18 Apr 2022 19:21:43 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S243181AbiDRTYV (ORCPT ); Mon, 18 Apr 2022 15:24:21 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44794 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1347676AbiDRTYU (ORCPT ); Mon, 18 Apr 2022 15:24:20 -0400 Received: from ams.source.kernel.org (ams.source.kernel.org [IPv6:2604:1380:4601:e00::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0D9D035862 for ; Mon, 18 Apr 2022 12:21:41 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id BA2CDB81060 for ; Mon, 18 Apr 2022 19:21:39 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 2B1C7C385A1; Mon, 18 Apr 2022 19:21:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1650309698; bh=DwEYq/7mM8vKR7Riro/yQEtxNUp3+whQUQAx1xp/Xy0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=jvfXLRKaFeKs+4B7mXivDxGytWkHCJSpbDa97+iSpn4iQxgBLrcYPjsJ3tCBrbdOW ClOReEKKWCAefqMTjlelm+mj/M9z599IVo3qyME4vS645tZ3Lm4DUlI6PBMNx9z2C0 VXPlxzMDoJhuCLcLNaEd1CtZkvH50Ti9/T8MzBqXH/NM1tfj1FM/GWvSSXUpQCVcL+ PnQCwCCFzQUigwu45HkTvg8jnYgMk2parWLczYchjP9j160eKcl1dLTTowAFgrhdax cebj4hRN9ZWLsxOuobBcAzO3xRkemUbgD0kdycb2x5l4GcosfpCFZotXrvChKcGmKJ IB95cZ2WVV84g== From: Jonathan Cameron To: linux-iio@vger.kernel.org Cc: Michael Hennerich , Lars-Peter Clausen , Vincent Whitchurch , Jonathan Cameron Subject: [PATCH 15/17] iio: cdc: ad7746: Add device specific ABI documentation. Date: Mon, 18 Apr 2022 20:29:05 +0100 Message-Id: <20220418192907.763933-16-jic23@kernel.org> X-Mailer: git-send-email 2.35.3 In-Reply-To: <20220418192907.763933-1-jic23@kernel.org> References: <20220418192907.763933-1-jic23@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org From: Jonathan Cameron The datasheet description of offset calibration is complex, so for that on just refer the reader to the device datasheet. Signed-off-by: Jonathan Cameron --- Documentation/ABI/testing/sysfs-bus-iio-cdc-ad7746 | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-bus-iio-cdc-ad7746 b/Documentation/ABI/testing/sysfs-bus-iio-cdc-ad7746 new file mode 100644 index 000000000000..6db81725b5d2 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-bus-iio-cdc-ad7746 @@ -0,0 +1,11 @@ +What: /sys/.../iio:deviceX/in_capacitableY_calibbias_calibration +What: /sys/.../iio:deviceX/in_capacitableY_calibscale_calibration +KernelVersion: 5.19 +Contact: linux-iio@vger.kernel.org +Description: + Write 1 to trigger a calibration of the calibbias or + calibscale. For calibscale, a fullscale capacitance should + be connected to the capacitance input and a + calibscale_calibration then started. For calibbias see + the device datasheet section on "capacitive system offset + calibration". From patchwork Mon Apr 18 19:29:06 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonathan Cameron X-Patchwork-Id: 12817075 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 22D86C433EF for ; Mon, 18 Apr 2022 19:21:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1347661AbiDRTY1 (ORCPT ); Mon, 18 Apr 2022 15:24:27 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44854 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1347657AbiDRTYZ (ORCPT ); Mon, 18 Apr 2022 15:24:25 -0400 Received: from ams.source.kernel.org (ams.source.kernel.org [IPv6:2604:1380:4601:e00::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0B76D35862 for ; Mon, 18 Apr 2022 12:21:44 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id 6FAECB81060 for ; Mon, 18 Apr 2022 19:21:42 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 0593AC385A7; Mon, 18 Apr 2022 19:21:38 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1650309701; bh=Oygu+vHBT5KuH960iBNCErMwun2y1B7SP6EHngh8Zmk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Enu7UL7PZPBp5KVy3PLZGiYCwrUE9gYBRXkM8B5x2RqCNW7Yhah1ZU78qwxqxTqMg /2FT68nBZUe0HB0tjlPoePztt4+I9kJd/cl+Mhnf6wHH1Y4KpFi1gjCiFaV+1WsVos brEFCcGlIRW3MuTapi9H53nPyWMaNNc1MBcFImRDCy+Zi7jPXQCExMhMr2zXboF3kI xXc7XL3EviyYhKVQbwyAQz2dTiWfMsrI7sRKOfUEyIFVKmCI6DmYEkeUHcjV6dCb0w fKGIu2RBonPCcF6ehvEmzaEbOgx9wbljlMcbuZqDHxi39/UCFoIi089NveQaPcbAKt 0ClfqFJfgJNIg== From: Jonathan Cameron To: linux-iio@vger.kernel.org Cc: Michael Hennerich , Lars-Peter Clausen , Vincent Whitchurch , Jonathan Cameron Subject: [PATCH 16/17] iio: cdc: ad7746: Move driver out of staging. Date: Mon, 18 Apr 2022 20:29:06 +0100 Message-Id: <20220418192907.763933-17-jic23@kernel.org> X-Mailer: git-send-email 2.35.3 In-Reply-To: <20220418192907.763933-1-jic23@kernel.org> References: <20220418192907.763933-1-jic23@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org From: Jonathan Cameron All known major issues with this driver resolved so time to move it out of staging. Note this cleanup work was done using the roadtest framework. https://lore.kernel.org/all/20220311162445.346685-1-vincent.whitchurch@axis.com/ Signed-off-by: Jonathan Cameron --- drivers/iio/cdc/Kconfig | 10 + drivers/iio/cdc/Makefile | 1 + drivers/iio/cdc/ad7746.c | 818 +++++++++++++++++++++++++++++++ drivers/staging/iio/cdc/ad7746.c | 818 ------------------------------- 4 files changed, 829 insertions(+), 818 deletions(-) diff --git a/drivers/iio/cdc/Kconfig b/drivers/iio/cdc/Kconfig index 5e3319a3ff48..e0a5ce66a984 100644 --- a/drivers/iio/cdc/Kconfig +++ b/drivers/iio/cdc/Kconfig @@ -14,4 +14,14 @@ config AD7150 To compile this driver as a module, choose M here: the module will be called ad7150. +config AD7746 + tristate "Analog Devices AD7745, AD7746 AD7747 capacitive sensor driver" + depends on I2C + help + Say yes here to build support for Analog Devices capacitive sensors. + (AD7745, AD7746, AD7747) Provides direct access via sysfs. + + To compile this driver as a module, choose M here: the + module will be called ad7746. + endmenu diff --git a/drivers/iio/cdc/Makefile b/drivers/iio/cdc/Makefile index ee490637b032..41db756d8020 100644 --- a/drivers/iio/cdc/Makefile +++ b/drivers/iio/cdc/Makefile @@ -4,3 +4,4 @@ # obj-$(CONFIG_AD7150) += ad7150.o +obj-$(CONFIG_AD7746) += ad7746.o diff --git a/drivers/iio/cdc/ad7746.c b/drivers/iio/cdc/ad7746.c new file mode 100644 index 000000000000..058f1b74122e --- /dev/null +++ b/drivers/iio/cdc/ad7746.c @@ -0,0 +1,818 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * AD7746 capacitive sensor driver supporting AD7745, AD7746 and AD7747 + * + * Copyright 2011 Analog Devices Inc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +/* AD7746 Register Definition */ + +#define AD7746_REG_STATUS 0 +#define AD7746_REG_CAP_DATA_HIGH 1 +#define AD7746_REG_VT_DATA_HIGH 4 +#define AD7746_REG_CAP_SETUP 7 +#define AD7746_REG_VT_SETUP 8 +#define AD7746_REG_EXC_SETUP 9 +#define AD7746_REG_CFG 10 +#define AD7746_REG_CAPDACA 11 +#define AD7746_REG_CAPDACB 12 +#define AD7746_REG_CAP_OFFH 13 +#define AD7746_REG_CAP_GAINH 15 +#define AD7746_REG_VOLT_GAINH 17 + +/* Status Register Bit Designations (AD7746_REG_STATUS) */ +#define AD7746_STATUS_EXCERR BIT(3) +#define AD7746_STATUS_RDY BIT(2) +#define AD7746_STATUS_RDYVT BIT(1) +#define AD7746_STATUS_RDYCAP BIT(0) + +/* Capacitive Channel Setup Register Bit Designations (AD7746_REG_CAP_SETUP) */ +#define AD7746_CAPSETUP_CAPEN BIT(7) +#define AD7746_CAPSETUP_CIN2 BIT(6) /* AD7746 only */ +#define AD7746_CAPSETUP_CAPDIFF BIT(5) +#define AD7746_CAPSETUP_CACHOP BIT(0) + +/* Voltage/Temperature Setup Register Bit Designations (AD7746_REG_VT_SETUP) */ +#define AD7746_VTSETUP_VTEN BIT(7) +#define AD7746_VTSETUP_VTMD_MASK GENMASK(6, 5) +#define AD7746_VTSETUP_VTMD_INT_TEMP 0 +#define AD7746_VTSETUP_VTMD_EXT_TEMP 1 +#define AD7746_VTSETUP_VTMD_VDD_MON 2 +#define AD7746_VTSETUP_VTMD_EXT_VIN 3 +#define AD7746_VTSETUP_EXTREF BIT(4) +#define AD7746_VTSETUP_VTSHORT BIT(1) +#define AD7746_VTSETUP_VTCHOP BIT(0) + +/* Excitation Setup Register Bit Designations (AD7746_REG_EXC_SETUP) */ +#define AD7746_EXCSETUP_CLKCTRL BIT(7) +#define AD7746_EXCSETUP_EXCON BIT(6) +#define AD7746_EXCSETUP_EXCB BIT(5) +#define AD7746_EXCSETUP_NEXCB BIT(4) +#define AD7746_EXCSETUP_EXCA BIT(3) +#define AD7746_EXCSETUP_NEXCA BIT(2) +#define AD7746_EXCSETUP_EXCLVL_MASK GENMASK(1, 0) + +/* Config Register Bit Designations (AD7746_REG_CFG) */ +#define AD7746_CONF_VTFS_MASK GENMASK(7, 6) +#define AD7746_CONF_CAPFS_MASK GENMASK(5, 3) +#define AD7746_CONF_MODE_MASK GENMASK(2, 0) +#define AD7746_CONF_MODE_IDLE 0 +#define AD7746_CONF_MODE_CONT_CONV 1 +#define AD7746_CONF_MODE_SINGLE_CONV 2 +#define AD7746_CONF_MODE_PWRDN 3 +#define AD7746_CONF_MODE_OFFS_CAL 5 +#define AD7746_CONF_MODE_GAIN_CAL 6 + +/* CAPDAC Register Bit Designations (AD7746_REG_CAPDACx) */ +#define AD7746_CAPDAC_DACEN BIT(7) +#define AD7746_CAPDAC_DACP_MASK 0x7F + +struct ad7746_chip_info { + struct i2c_client *client; + struct mutex lock; /* protect sensor state */ + /* + * Capacitive channel digital filter setup; + * conversion time/update rate setup per channel + */ + u8 config; + u8 cap_setup; + u8 vt_setup; + u8 capdac[2][2]; + s8 capdac_set; +}; + +enum ad7746_chan { + VIN, + VIN_VDD, + TEMP_INT, + TEMP_EXT, + CIN1, + CIN1_DIFF, + CIN2, + CIN2_DIFF, +}; + +struct ad7746_chan_info { + u8 addr; + union { + u8 vtmd; + struct { /* CAP SETUP fields */ + unsigned int cin2 : 1; + unsigned int capdiff : 1; + }; + }; +}; + +static const struct ad7746_chan_info ad7746_chan_info[] = { + [VIN] = { + .addr = AD7746_REG_VT_DATA_HIGH, + .vtmd = AD7746_VTSETUP_VTMD_EXT_VIN, + }, + [VIN_VDD] = { + .addr = AD7746_REG_VT_DATA_HIGH, + .vtmd = AD7746_VTSETUP_VTMD_VDD_MON, + }, + [TEMP_INT] = { + .addr = AD7746_REG_VT_DATA_HIGH, + .vtmd = AD7746_VTSETUP_VTMD_INT_TEMP, + }, + [TEMP_EXT] = { + .addr = AD7746_REG_VT_DATA_HIGH, + .vtmd = AD7746_VTSETUP_VTMD_EXT_TEMP, + }, + [CIN1] = { + .addr = AD7746_REG_CAP_DATA_HIGH, + }, + [CIN1_DIFF] = { + .addr = AD7746_REG_CAP_DATA_HIGH, + .capdiff = 1, + }, + [CIN2] = { + .addr = AD7746_REG_CAP_DATA_HIGH, + .cin2 = 1, + }, + [CIN2_DIFF] = { + .addr = AD7746_REG_CAP_DATA_HIGH, + .cin2 = 1, + .capdiff = 1, + }, +}; + +static const struct iio_chan_spec ad7746_channels[] = { + [VIN] = { + .type = IIO_VOLTAGE, + .indexed = 1, + .channel = 0, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ), + .info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_SAMP_FREQ), + .address = VIN, + }, + [VIN_VDD] = { + .type = IIO_VOLTAGE, + .indexed = 1, + .channel = 1, + .extend_name = "supply", + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ), + .info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_SAMP_FREQ), + .address = VIN_VDD, + }, + [TEMP_INT] = { + .type = IIO_TEMP, + .indexed = 1, + .channel = 0, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), + .address = TEMP_INT, + }, + [TEMP_EXT] = { + .type = IIO_TEMP, + .indexed = 1, + .channel = 1, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), + .address = TEMP_EXT, + }, + [CIN1] = { + .type = IIO_CAPACITANCE, + .indexed = 1, + .channel = 0, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_CALIBSCALE) | BIT(IIO_CHAN_INFO_OFFSET), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_CALIBBIAS) | + BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_SAMP_FREQ), + .info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_SAMP_FREQ), + .address = CIN1, + }, + [CIN1_DIFF] = { + .type = IIO_CAPACITANCE, + .differential = 1, + .indexed = 1, + .channel = 0, + .channel2 = 2, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_CALIBSCALE) | BIT(IIO_CHAN_INFO_INPUTOFFSET), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_CALIBBIAS) | + BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_SAMP_FREQ), + .info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_SAMP_FREQ), + .address = CIN1_DIFF, + }, + [CIN2] = { + .type = IIO_CAPACITANCE, + .indexed = 1, + .channel = 1, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_CALIBSCALE) | BIT(IIO_CHAN_INFO_OFFSET), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_CALIBBIAS) | + BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_SAMP_FREQ), + .info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_SAMP_FREQ), + .address = CIN2, + }, + [CIN2_DIFF] = { + .type = IIO_CAPACITANCE, + .differential = 1, + .indexed = 1, + .channel = 1, + .channel2 = 3, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_CALIBSCALE) | BIT(IIO_CHAN_INFO_INPUTOFFSET), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_CALIBBIAS) | + BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_SAMP_FREQ), + .info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_SAMP_FREQ), + .address = CIN2_DIFF, + } +}; + +/* Values are Update Rate (Hz), Conversion Time (ms) + 1*/ +static const unsigned char ad7746_vt_filter_rate_table[][2] = { + { 50, 20 + 1 }, { 31, 32 + 1 }, { 16, 62 + 1 }, { 8, 122 + 1 }, +}; + +static const unsigned char ad7746_cap_filter_rate_table[][2] = { + { 91, 11 + 1 }, { 84, 12 + 1 }, { 50, 20 + 1 }, { 26, 38 + 1 }, + { 16, 62 + 1 }, { 13, 77 + 1 }, { 11, 92 + 1 }, { 9, 110 + 1 }, +}; + +static int ad7746_set_capdac(struct ad7746_chip_info *chip, int channel) +{ + int ret = i2c_smbus_write_byte_data(chip->client, + AD7746_REG_CAPDACA, + chip->capdac[channel][0]); + if (ret < 0) + return ret; + + return i2c_smbus_write_byte_data(chip->client, + AD7746_REG_CAPDACB, + chip->capdac[channel][1]); +} + +static int ad7746_select_channel(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan) +{ + struct ad7746_chip_info *chip = iio_priv(indio_dev); + u8 vt_setup, cap_setup; + int ret, delay, idx; + + switch (chan->type) { + case IIO_CAPACITANCE: + cap_setup = FIELD_PREP(AD7746_CAPSETUP_CIN2, + ad7746_chan_info[chan->address].cin2) | + FIELD_PREP(AD7746_CAPSETUP_CAPDIFF, + ad7746_chan_info[chan->address].capdiff) | + FIELD_PREP(AD7746_CAPSETUP_CAPEN, 1); + vt_setup = chip->vt_setup & ~AD7746_VTSETUP_VTEN; + idx = FIELD_GET(AD7746_CONF_CAPFS_MASK, chip->config); + delay = ad7746_cap_filter_rate_table[idx][1]; + + ret = ad7746_set_capdac(chip, chan->channel); + if (ret < 0) + return ret; + + if (chip->capdac_set != chan->channel) + chip->capdac_set = chan->channel; + break; + case IIO_VOLTAGE: + case IIO_TEMP: + vt_setup = FIELD_PREP(AD7746_VTSETUP_VTMD_MASK, + ad7746_chan_info[chan->address].vtmd) | + FIELD_PREP(AD7746_VTSETUP_VTEN, 1); + cap_setup = chip->cap_setup & ~AD7746_CAPSETUP_CAPEN; + idx = FIELD_GET(AD7746_CONF_VTFS_MASK, chip->config); + delay = ad7746_cap_filter_rate_table[idx][1]; + break; + default: + return -EINVAL; + } + + if (chip->cap_setup != cap_setup) { + ret = i2c_smbus_write_byte_data(chip->client, + AD7746_REG_CAP_SETUP, + cap_setup); + if (ret < 0) + return ret; + + chip->cap_setup = cap_setup; + } + + if (chip->vt_setup != vt_setup) { + ret = i2c_smbus_write_byte_data(chip->client, + AD7746_REG_VT_SETUP, + vt_setup); + if (ret < 0) + return ret; + + chip->vt_setup = vt_setup; + } + + return delay; +} + +static inline ssize_t ad7746_start_calib(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len, + u8 regval) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct ad7746_chip_info *chip = iio_priv(indio_dev); + int ret, timeout = 10; + bool doit; + + ret = strtobool(buf, &doit); + if (ret < 0) + return ret; + + if (!doit) + return 0; + + mutex_lock(&chip->lock); + regval |= chip->config; + ret = i2c_smbus_write_byte_data(chip->client, AD7746_REG_CFG, regval); + if (ret < 0) + goto unlock; + + do { + msleep(20); + ret = i2c_smbus_read_byte_data(chip->client, AD7746_REG_CFG); + if (ret < 0) + goto unlock; + + } while ((ret == regval) && timeout--); + + mutex_unlock(&chip->lock); + + return len; + +unlock: + mutex_unlock(&chip->lock); + return ret; +} + +static ssize_t ad7746_start_offset_calib(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + int ret = ad7746_select_channel(indio_dev, + &ad7746_channels[to_iio_dev_attr(attr)->address]); + if (ret < 0) + return ret; + + return ad7746_start_calib(dev, attr, buf, len, + FIELD_PREP(AD7746_CONF_MODE_MASK, + AD7746_CONF_MODE_OFFS_CAL)); +} + +static ssize_t ad7746_start_gain_calib(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + int ret = ad7746_select_channel(indio_dev, + &ad7746_channels[to_iio_dev_attr(attr)->address]); + if (ret < 0) + return ret; + + return ad7746_start_calib(dev, attr, buf, len, + FIELD_PREP(AD7746_CONF_MODE_MASK, + AD7746_CONF_MODE_GAIN_CAL)); +} + +static IIO_DEVICE_ATTR(in_capacitance0_calibbias_calibration, + 0200, NULL, ad7746_start_offset_calib, CIN1); +static IIO_DEVICE_ATTR(in_capacitance1_calibbias_calibration, + 0200, NULL, ad7746_start_offset_calib, CIN2); +static IIO_DEVICE_ATTR(in_capacitance0_calibscale_calibration, + 0200, NULL, ad7746_start_gain_calib, CIN1); +static IIO_DEVICE_ATTR(in_capacitance1_calibscale_calibration, + 0200, NULL, ad7746_start_gain_calib, CIN2); +static IIO_DEVICE_ATTR(in_voltage0_calibscale_calibration, + 0200, NULL, ad7746_start_gain_calib, VIN); + +static int ad7746_store_cap_filter_rate_setup(struct ad7746_chip_info *chip, + int val) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(ad7746_cap_filter_rate_table); i++) + if (val >= ad7746_cap_filter_rate_table[i][0]) + break; + + if (i >= ARRAY_SIZE(ad7746_cap_filter_rate_table)) + i = ARRAY_SIZE(ad7746_cap_filter_rate_table) - 1; + + chip->config &= ~AD7746_CONF_CAPFS_MASK; + chip->config |= FIELD_PREP(AD7746_CONF_CAPFS_MASK, i); + + return 0; +} + +static int ad7746_store_vt_filter_rate_setup(struct ad7746_chip_info *chip, + int val) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(ad7746_vt_filter_rate_table); i++) + if (val >= ad7746_vt_filter_rate_table[i][0]) + break; + + if (i >= ARRAY_SIZE(ad7746_vt_filter_rate_table)) + i = ARRAY_SIZE(ad7746_vt_filter_rate_table) - 1; + + chip->config &= ~AD7746_CONF_VTFS_MASK; + chip->config |= FIELD_PREP(AD7746_CONF_VTFS_MASK, i); + + return 0; +} + +static struct attribute *ad7746_attributes[] = { + &iio_dev_attr_in_capacitance0_calibbias_calibration.dev_attr.attr, + &iio_dev_attr_in_capacitance0_calibscale_calibration.dev_attr.attr, + &iio_dev_attr_in_capacitance1_calibscale_calibration.dev_attr.attr, + &iio_dev_attr_in_capacitance1_calibbias_calibration.dev_attr.attr, + &iio_dev_attr_in_voltage0_calibscale_calibration.dev_attr.attr, + NULL, +}; + +static const struct attribute_group ad7746_attribute_group = { + .attrs = ad7746_attributes, +}; + +static int ad7746_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, + int val2, + long mask) +{ + struct ad7746_chip_info *chip = iio_priv(indio_dev); + int ret, reg; + + switch (mask) { + case IIO_CHAN_INFO_CALIBSCALE: + if (val != 1) + return -EINVAL; + + val = (val2 * 1024) / 15625; + + switch (chan->type) { + case IIO_CAPACITANCE: + reg = AD7746_REG_CAP_GAINH; + break; + case IIO_VOLTAGE: + reg = AD7746_REG_VOLT_GAINH; + break; + default: + return -EINVAL; + } + + mutex_lock(&chip->lock); + ret = i2c_smbus_write_word_swapped(chip->client, reg, val); + mutex_unlock(&chip->lock); + if (ret < 0) + return ret; + + return 0; + case IIO_CHAN_INFO_CALIBBIAS: + if (val < 0 || val > 0xFFFF) + return -EINVAL; + + mutex_lock(&chip->lock); + ret = i2c_smbus_write_word_swapped(chip->client, + AD7746_REG_CAP_OFFH, val); + mutex_unlock(&chip->lock); + if (ret < 0) + return ret; + + return 0; + case IIO_CHAN_INFO_OFFSET: + case IIO_CHAN_INFO_INPUTOFFSET: + if (val < 0 || val > 43008000) /* 21pF */ + return -EINVAL; + + /* + * CAPDAC Scale = 21pF_typ / 127 + * CIN Scale = 8.192pF / 2^24 + * Offset Scale = CAPDAC Scale / CIN Scale = 338646 + */ + + val /= 338646; + mutex_lock(&chip->lock); + chip->capdac[chan->channel][chan->differential] = val > 0 ? + FIELD_PREP(AD7746_CAPDAC_DACP_MASK, val) | AD7746_CAPDAC_DACEN : 0; + + ret = ad7746_set_capdac(chip, chan->channel); + if (ret < 0) { + mutex_unlock(&chip->lock); + return ret; + } + + chip->capdac_set = chan->channel; + mutex_unlock(&chip->lock); + + return 0; + case IIO_CHAN_INFO_SAMP_FREQ: + if (val2) + return -EINVAL; + + switch (chan->type) { + case IIO_CAPACITANCE: + mutex_lock(&chip->lock); + ret = ad7746_store_cap_filter_rate_setup(chip, val); + mutex_unlock(&chip->lock); + return ret; + case IIO_VOLTAGE: + mutex_lock(&chip->lock); + ret = ad7746_store_vt_filter_rate_setup(chip, val); + mutex_unlock(&chip->lock); + return ret; + default: + return -EINVAL; + } + default: + return -EINVAL; + } +} + +static const int ad7746_v_samp_freq[] = { 50, 31, 16, 8, }; +static const int ad7746_cap_samp_freq[] = { 91, 84, 50, 26, 16, 13, 11, 9, }; + +static int ad7746_read_avail(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, const int **vals, + int *type, int *length, long mask) +{ + if (mask != IIO_CHAN_INFO_SAMP_FREQ) + return -EINVAL; + + switch (chan->type) { + case IIO_VOLTAGE: + *vals = ad7746_v_samp_freq; + *length = ARRAY_SIZE(ad7746_v_samp_freq); + break; + case IIO_CAPACITANCE: + *vals = ad7746_cap_samp_freq; + *length = ARRAY_SIZE(ad7746_cap_samp_freq); + break; + default: + return -EINVAL; + } + *type = IIO_VAL_INT; + return IIO_AVAIL_LIST; +} + +static int ad7746_read_channel(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val) +{ + struct ad7746_chip_info *chip = iio_priv(indio_dev); + int ret, delay; + u8 data[3]; + u8 regval; + + ret = ad7746_select_channel(indio_dev, chan); + if (ret < 0) + return ret; + delay = ret; + + regval = chip->config | FIELD_PREP(AD7746_CONF_MODE_MASK, + AD7746_CONF_MODE_SINGLE_CONV); + ret = i2c_smbus_write_byte_data(chip->client, AD7746_REG_CFG, regval); + if (ret < 0) + return ret; + + msleep(delay); + /* Now read the actual register */ + ret = i2c_smbus_read_i2c_block_data(chip->client, + ad7746_chan_info[chan->address].addr, + 3, data); + if (ret < 0) + return ret; + + /* + * Offset applied internally becaue the _offset userspace interface is + * needed for the CAP DACs which apply a controllable offset. + */ + *val = get_unaligned_be24(data) - 0x800000; + + return 0; +} + +static int ad7746_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, + long mask) +{ + struct ad7746_chip_info *chip = iio_priv(indio_dev); + int ret, idx; + u8 reg; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + mutex_lock(&chip->lock); + ret = ad7746_read_channel(indio_dev, chan, val); + mutex_unlock(&chip->lock); + if (ret < 0) + return ret; + + return IIO_VAL_INT; + case IIO_CHAN_INFO_CALIBSCALE: + switch (chan->type) { + case IIO_CAPACITANCE: + reg = AD7746_REG_CAP_GAINH; + break; + case IIO_VOLTAGE: + reg = AD7746_REG_VOLT_GAINH; + break; + default: + return -EINVAL; + } + + mutex_lock(&chip->lock); + ret = i2c_smbus_read_word_swapped(chip->client, reg); + mutex_unlock(&chip->lock); + if (ret < 0) + return ret; + /* 1 + gain_val / 2^16 */ + *val = 1; + *val2 = (15625 * ret) / 1024; + + return IIO_VAL_INT_PLUS_MICRO; + case IIO_CHAN_INFO_CALIBBIAS: + mutex_lock(&chip->lock); + ret = i2c_smbus_read_word_swapped(chip->client, + AD7746_REG_CAP_OFFH); + mutex_unlock(&chip->lock); + if (ret < 0) + return ret; + *val = ret; + + return IIO_VAL_INT; + case IIO_CHAN_INFO_OFFSET: + case IIO_CHAN_INFO_INPUTOFFSET: + *val = FIELD_GET(AD7746_CAPDAC_DACP_MASK, + chip->capdac[chan->channel][chan->differential]) * 338646; + + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + switch (chan->type) { + case IIO_CAPACITANCE: + /* 8.192pf / 2^24 */ + *val = 0; + *val2 = 488; + return IIO_VAL_INT_PLUS_NANO; + case IIO_VOLTAGE: + /* 1170mV / 2^23 */ + *val = 1170; + if (chan->channel == 1) + *val *= 6; + *val2 = 23; + return IIO_VAL_FRACTIONAL_LOG2; + case IIO_TEMP: + *val = 125; + *val2 = 8; + return IIO_VAL_FRACTIONAL_LOG2; + default: + return -EINVAL; + } + case IIO_CHAN_INFO_SAMP_FREQ: + switch (chan->type) { + case IIO_CAPACITANCE: + idx = FIELD_GET(AD7746_CONF_CAPFS_MASK, chip->config); + *val = ad7746_cap_filter_rate_table[idx][0]; + return IIO_VAL_INT; + case IIO_VOLTAGE: + idx = FIELD_GET(AD7746_CONF_VTFS_MASK, chip->config); + *val = ad7746_vt_filter_rate_table[idx][0]; + return IIO_VAL_INT; + default: + return -EINVAL; + } + default: + return -EINVAL; + } +} + +static const struct iio_info ad7746_info = { + .attrs = &ad7746_attribute_group, + .read_raw = ad7746_read_raw, + .read_avail = ad7746_read_avail, + .write_raw = ad7746_write_raw, +}; + +static int ad7746_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct device *dev = &client->dev; + struct ad7746_chip_info *chip; + struct iio_dev *indio_dev; + unsigned char regval = 0; + unsigned int vdd_permille; + int ret; + + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*chip)); + if (!indio_dev) + return -ENOMEM; + + chip = iio_priv(indio_dev); + mutex_init(&chip->lock); + + chip->client = client; + chip->capdac_set = -1; + + indio_dev->name = id->name; + indio_dev->info = &ad7746_info; + indio_dev->channels = ad7746_channels; + if (id->driver_data == 7746) + indio_dev->num_channels = ARRAY_SIZE(ad7746_channels); + else + indio_dev->num_channels = ARRAY_SIZE(ad7746_channels) - 2; + indio_dev->modes = INDIO_DIRECT_MODE; + + if (device_property_read_bool(dev, "adi,exca-output-en")) { + if (device_property_read_bool(dev, "adi,exca-output-invert")) + regval |= AD7746_EXCSETUP_NEXCA; + else + regval |= AD7746_EXCSETUP_EXCA; + } + + if (device_property_read_bool(dev, "adi,excb-output-en")) { + if (device_property_read_bool(dev, "adi,excb-output-invert")) + regval |= AD7746_EXCSETUP_NEXCB; + else + regval |= AD7746_EXCSETUP_EXCB; + } + + ret = device_property_read_u32(dev, "adi,excitation-vdd-permille", + &vdd_permille); + if (!ret) { + switch (vdd_permille) { + case 125: + regval |= FIELD_PREP(AD7746_EXCSETUP_EXCLVL_MASK, 0); + break; + case 250: + regval |= FIELD_PREP(AD7746_EXCSETUP_EXCLVL_MASK, 1); + break; + case 375: + regval |= FIELD_PREP(AD7746_EXCSETUP_EXCLVL_MASK, 2); + break; + case 500: + regval |= FIELD_PREP(AD7746_EXCSETUP_EXCLVL_MASK, 3); + break; + default: + break; + } + } + + ret = i2c_smbus_write_byte_data(chip->client, AD7746_REG_EXC_SETUP, + regval); + if (ret < 0) + return ret; + + return devm_iio_device_register(indio_dev->dev.parent, indio_dev); +} + +static const struct i2c_device_id ad7746_id[] = { + { "ad7745", 7745 }, + { "ad7746", 7746 }, + { "ad7747", 7747 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, ad7746_id); + +static const struct of_device_id ad7746_of_match[] = { + { .compatible = "adi,ad7745" }, + { .compatible = "adi,ad7746" }, + { .compatible = "adi,ad7747" }, + { }, +}; +MODULE_DEVICE_TABLE(of, ad7746_of_match); + +static struct i2c_driver ad7746_driver = { + .driver = { + .name = KBUILD_MODNAME, + .of_match_table = ad7746_of_match, + }, + .probe = ad7746_probe, + .id_table = ad7746_id, +}; +module_i2c_driver(ad7746_driver); + +MODULE_AUTHOR("Michael Hennerich "); +MODULE_DESCRIPTION("Analog Devices AD7746/5/7 capacitive sensor driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/iio/cdc/ad7746.c b/drivers/staging/iio/cdc/ad7746.c deleted file mode 100644 index 058f1b74122e..000000000000 --- a/drivers/staging/iio/cdc/ad7746.c +++ /dev/null @@ -1,818 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * AD7746 capacitive sensor driver supporting AD7745, AD7746 and AD7747 - * - * Copyright 2011 Analog Devices Inc. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -/* AD7746 Register Definition */ - -#define AD7746_REG_STATUS 0 -#define AD7746_REG_CAP_DATA_HIGH 1 -#define AD7746_REG_VT_DATA_HIGH 4 -#define AD7746_REG_CAP_SETUP 7 -#define AD7746_REG_VT_SETUP 8 -#define AD7746_REG_EXC_SETUP 9 -#define AD7746_REG_CFG 10 -#define AD7746_REG_CAPDACA 11 -#define AD7746_REG_CAPDACB 12 -#define AD7746_REG_CAP_OFFH 13 -#define AD7746_REG_CAP_GAINH 15 -#define AD7746_REG_VOLT_GAINH 17 - -/* Status Register Bit Designations (AD7746_REG_STATUS) */ -#define AD7746_STATUS_EXCERR BIT(3) -#define AD7746_STATUS_RDY BIT(2) -#define AD7746_STATUS_RDYVT BIT(1) -#define AD7746_STATUS_RDYCAP BIT(0) - -/* Capacitive Channel Setup Register Bit Designations (AD7746_REG_CAP_SETUP) */ -#define AD7746_CAPSETUP_CAPEN BIT(7) -#define AD7746_CAPSETUP_CIN2 BIT(6) /* AD7746 only */ -#define AD7746_CAPSETUP_CAPDIFF BIT(5) -#define AD7746_CAPSETUP_CACHOP BIT(0) - -/* Voltage/Temperature Setup Register Bit Designations (AD7746_REG_VT_SETUP) */ -#define AD7746_VTSETUP_VTEN BIT(7) -#define AD7746_VTSETUP_VTMD_MASK GENMASK(6, 5) -#define AD7746_VTSETUP_VTMD_INT_TEMP 0 -#define AD7746_VTSETUP_VTMD_EXT_TEMP 1 -#define AD7746_VTSETUP_VTMD_VDD_MON 2 -#define AD7746_VTSETUP_VTMD_EXT_VIN 3 -#define AD7746_VTSETUP_EXTREF BIT(4) -#define AD7746_VTSETUP_VTSHORT BIT(1) -#define AD7746_VTSETUP_VTCHOP BIT(0) - -/* Excitation Setup Register Bit Designations (AD7746_REG_EXC_SETUP) */ -#define AD7746_EXCSETUP_CLKCTRL BIT(7) -#define AD7746_EXCSETUP_EXCON BIT(6) -#define AD7746_EXCSETUP_EXCB BIT(5) -#define AD7746_EXCSETUP_NEXCB BIT(4) -#define AD7746_EXCSETUP_EXCA BIT(3) -#define AD7746_EXCSETUP_NEXCA BIT(2) -#define AD7746_EXCSETUP_EXCLVL_MASK GENMASK(1, 0) - -/* Config Register Bit Designations (AD7746_REG_CFG) */ -#define AD7746_CONF_VTFS_MASK GENMASK(7, 6) -#define AD7746_CONF_CAPFS_MASK GENMASK(5, 3) -#define AD7746_CONF_MODE_MASK GENMASK(2, 0) -#define AD7746_CONF_MODE_IDLE 0 -#define AD7746_CONF_MODE_CONT_CONV 1 -#define AD7746_CONF_MODE_SINGLE_CONV 2 -#define AD7746_CONF_MODE_PWRDN 3 -#define AD7746_CONF_MODE_OFFS_CAL 5 -#define AD7746_CONF_MODE_GAIN_CAL 6 - -/* CAPDAC Register Bit Designations (AD7746_REG_CAPDACx) */ -#define AD7746_CAPDAC_DACEN BIT(7) -#define AD7746_CAPDAC_DACP_MASK 0x7F - -struct ad7746_chip_info { - struct i2c_client *client; - struct mutex lock; /* protect sensor state */ - /* - * Capacitive channel digital filter setup; - * conversion time/update rate setup per channel - */ - u8 config; - u8 cap_setup; - u8 vt_setup; - u8 capdac[2][2]; - s8 capdac_set; -}; - -enum ad7746_chan { - VIN, - VIN_VDD, - TEMP_INT, - TEMP_EXT, - CIN1, - CIN1_DIFF, - CIN2, - CIN2_DIFF, -}; - -struct ad7746_chan_info { - u8 addr; - union { - u8 vtmd; - struct { /* CAP SETUP fields */ - unsigned int cin2 : 1; - unsigned int capdiff : 1; - }; - }; -}; - -static const struct ad7746_chan_info ad7746_chan_info[] = { - [VIN] = { - .addr = AD7746_REG_VT_DATA_HIGH, - .vtmd = AD7746_VTSETUP_VTMD_EXT_VIN, - }, - [VIN_VDD] = { - .addr = AD7746_REG_VT_DATA_HIGH, - .vtmd = AD7746_VTSETUP_VTMD_VDD_MON, - }, - [TEMP_INT] = { - .addr = AD7746_REG_VT_DATA_HIGH, - .vtmd = AD7746_VTSETUP_VTMD_INT_TEMP, - }, - [TEMP_EXT] = { - .addr = AD7746_REG_VT_DATA_HIGH, - .vtmd = AD7746_VTSETUP_VTMD_EXT_TEMP, - }, - [CIN1] = { - .addr = AD7746_REG_CAP_DATA_HIGH, - }, - [CIN1_DIFF] = { - .addr = AD7746_REG_CAP_DATA_HIGH, - .capdiff = 1, - }, - [CIN2] = { - .addr = AD7746_REG_CAP_DATA_HIGH, - .cin2 = 1, - }, - [CIN2_DIFF] = { - .addr = AD7746_REG_CAP_DATA_HIGH, - .cin2 = 1, - .capdiff = 1, - }, -}; - -static const struct iio_chan_spec ad7746_channels[] = { - [VIN] = { - .type = IIO_VOLTAGE, - .indexed = 1, - .channel = 0, - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), - .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ), - .info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_SAMP_FREQ), - .address = VIN, - }, - [VIN_VDD] = { - .type = IIO_VOLTAGE, - .indexed = 1, - .channel = 1, - .extend_name = "supply", - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), - .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ), - .info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_SAMP_FREQ), - .address = VIN_VDD, - }, - [TEMP_INT] = { - .type = IIO_TEMP, - .indexed = 1, - .channel = 0, - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), - .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), - .address = TEMP_INT, - }, - [TEMP_EXT] = { - .type = IIO_TEMP, - .indexed = 1, - .channel = 1, - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), - .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), - .address = TEMP_EXT, - }, - [CIN1] = { - .type = IIO_CAPACITANCE, - .indexed = 1, - .channel = 0, - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | - BIT(IIO_CHAN_INFO_CALIBSCALE) | BIT(IIO_CHAN_INFO_OFFSET), - .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_CALIBBIAS) | - BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_SAMP_FREQ), - .info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_SAMP_FREQ), - .address = CIN1, - }, - [CIN1_DIFF] = { - .type = IIO_CAPACITANCE, - .differential = 1, - .indexed = 1, - .channel = 0, - .channel2 = 2, - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | - BIT(IIO_CHAN_INFO_CALIBSCALE) | BIT(IIO_CHAN_INFO_INPUTOFFSET), - .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_CALIBBIAS) | - BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_SAMP_FREQ), - .info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_SAMP_FREQ), - .address = CIN1_DIFF, - }, - [CIN2] = { - .type = IIO_CAPACITANCE, - .indexed = 1, - .channel = 1, - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | - BIT(IIO_CHAN_INFO_CALIBSCALE) | BIT(IIO_CHAN_INFO_OFFSET), - .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_CALIBBIAS) | - BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_SAMP_FREQ), - .info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_SAMP_FREQ), - .address = CIN2, - }, - [CIN2_DIFF] = { - .type = IIO_CAPACITANCE, - .differential = 1, - .indexed = 1, - .channel = 1, - .channel2 = 3, - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | - BIT(IIO_CHAN_INFO_CALIBSCALE) | BIT(IIO_CHAN_INFO_INPUTOFFSET), - .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_CALIBBIAS) | - BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_SAMP_FREQ), - .info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_SAMP_FREQ), - .address = CIN2_DIFF, - } -}; - -/* Values are Update Rate (Hz), Conversion Time (ms) + 1*/ -static const unsigned char ad7746_vt_filter_rate_table[][2] = { - { 50, 20 + 1 }, { 31, 32 + 1 }, { 16, 62 + 1 }, { 8, 122 + 1 }, -}; - -static const unsigned char ad7746_cap_filter_rate_table[][2] = { - { 91, 11 + 1 }, { 84, 12 + 1 }, { 50, 20 + 1 }, { 26, 38 + 1 }, - { 16, 62 + 1 }, { 13, 77 + 1 }, { 11, 92 + 1 }, { 9, 110 + 1 }, -}; - -static int ad7746_set_capdac(struct ad7746_chip_info *chip, int channel) -{ - int ret = i2c_smbus_write_byte_data(chip->client, - AD7746_REG_CAPDACA, - chip->capdac[channel][0]); - if (ret < 0) - return ret; - - return i2c_smbus_write_byte_data(chip->client, - AD7746_REG_CAPDACB, - chip->capdac[channel][1]); -} - -static int ad7746_select_channel(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan) -{ - struct ad7746_chip_info *chip = iio_priv(indio_dev); - u8 vt_setup, cap_setup; - int ret, delay, idx; - - switch (chan->type) { - case IIO_CAPACITANCE: - cap_setup = FIELD_PREP(AD7746_CAPSETUP_CIN2, - ad7746_chan_info[chan->address].cin2) | - FIELD_PREP(AD7746_CAPSETUP_CAPDIFF, - ad7746_chan_info[chan->address].capdiff) | - FIELD_PREP(AD7746_CAPSETUP_CAPEN, 1); - vt_setup = chip->vt_setup & ~AD7746_VTSETUP_VTEN; - idx = FIELD_GET(AD7746_CONF_CAPFS_MASK, chip->config); - delay = ad7746_cap_filter_rate_table[idx][1]; - - ret = ad7746_set_capdac(chip, chan->channel); - if (ret < 0) - return ret; - - if (chip->capdac_set != chan->channel) - chip->capdac_set = chan->channel; - break; - case IIO_VOLTAGE: - case IIO_TEMP: - vt_setup = FIELD_PREP(AD7746_VTSETUP_VTMD_MASK, - ad7746_chan_info[chan->address].vtmd) | - FIELD_PREP(AD7746_VTSETUP_VTEN, 1); - cap_setup = chip->cap_setup & ~AD7746_CAPSETUP_CAPEN; - idx = FIELD_GET(AD7746_CONF_VTFS_MASK, chip->config); - delay = ad7746_cap_filter_rate_table[idx][1]; - break; - default: - return -EINVAL; - } - - if (chip->cap_setup != cap_setup) { - ret = i2c_smbus_write_byte_data(chip->client, - AD7746_REG_CAP_SETUP, - cap_setup); - if (ret < 0) - return ret; - - chip->cap_setup = cap_setup; - } - - if (chip->vt_setup != vt_setup) { - ret = i2c_smbus_write_byte_data(chip->client, - AD7746_REG_VT_SETUP, - vt_setup); - if (ret < 0) - return ret; - - chip->vt_setup = vt_setup; - } - - return delay; -} - -static inline ssize_t ad7746_start_calib(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len, - u8 regval) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct ad7746_chip_info *chip = iio_priv(indio_dev); - int ret, timeout = 10; - bool doit; - - ret = strtobool(buf, &doit); - if (ret < 0) - return ret; - - if (!doit) - return 0; - - mutex_lock(&chip->lock); - regval |= chip->config; - ret = i2c_smbus_write_byte_data(chip->client, AD7746_REG_CFG, regval); - if (ret < 0) - goto unlock; - - do { - msleep(20); - ret = i2c_smbus_read_byte_data(chip->client, AD7746_REG_CFG); - if (ret < 0) - goto unlock; - - } while ((ret == regval) && timeout--); - - mutex_unlock(&chip->lock); - - return len; - -unlock: - mutex_unlock(&chip->lock); - return ret; -} - -static ssize_t ad7746_start_offset_calib(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - int ret = ad7746_select_channel(indio_dev, - &ad7746_channels[to_iio_dev_attr(attr)->address]); - if (ret < 0) - return ret; - - return ad7746_start_calib(dev, attr, buf, len, - FIELD_PREP(AD7746_CONF_MODE_MASK, - AD7746_CONF_MODE_OFFS_CAL)); -} - -static ssize_t ad7746_start_gain_calib(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - int ret = ad7746_select_channel(indio_dev, - &ad7746_channels[to_iio_dev_attr(attr)->address]); - if (ret < 0) - return ret; - - return ad7746_start_calib(dev, attr, buf, len, - FIELD_PREP(AD7746_CONF_MODE_MASK, - AD7746_CONF_MODE_GAIN_CAL)); -} - -static IIO_DEVICE_ATTR(in_capacitance0_calibbias_calibration, - 0200, NULL, ad7746_start_offset_calib, CIN1); -static IIO_DEVICE_ATTR(in_capacitance1_calibbias_calibration, - 0200, NULL, ad7746_start_offset_calib, CIN2); -static IIO_DEVICE_ATTR(in_capacitance0_calibscale_calibration, - 0200, NULL, ad7746_start_gain_calib, CIN1); -static IIO_DEVICE_ATTR(in_capacitance1_calibscale_calibration, - 0200, NULL, ad7746_start_gain_calib, CIN2); -static IIO_DEVICE_ATTR(in_voltage0_calibscale_calibration, - 0200, NULL, ad7746_start_gain_calib, VIN); - -static int ad7746_store_cap_filter_rate_setup(struct ad7746_chip_info *chip, - int val) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(ad7746_cap_filter_rate_table); i++) - if (val >= ad7746_cap_filter_rate_table[i][0]) - break; - - if (i >= ARRAY_SIZE(ad7746_cap_filter_rate_table)) - i = ARRAY_SIZE(ad7746_cap_filter_rate_table) - 1; - - chip->config &= ~AD7746_CONF_CAPFS_MASK; - chip->config |= FIELD_PREP(AD7746_CONF_CAPFS_MASK, i); - - return 0; -} - -static int ad7746_store_vt_filter_rate_setup(struct ad7746_chip_info *chip, - int val) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(ad7746_vt_filter_rate_table); i++) - if (val >= ad7746_vt_filter_rate_table[i][0]) - break; - - if (i >= ARRAY_SIZE(ad7746_vt_filter_rate_table)) - i = ARRAY_SIZE(ad7746_vt_filter_rate_table) - 1; - - chip->config &= ~AD7746_CONF_VTFS_MASK; - chip->config |= FIELD_PREP(AD7746_CONF_VTFS_MASK, i); - - return 0; -} - -static struct attribute *ad7746_attributes[] = { - &iio_dev_attr_in_capacitance0_calibbias_calibration.dev_attr.attr, - &iio_dev_attr_in_capacitance0_calibscale_calibration.dev_attr.attr, - &iio_dev_attr_in_capacitance1_calibscale_calibration.dev_attr.attr, - &iio_dev_attr_in_capacitance1_calibbias_calibration.dev_attr.attr, - &iio_dev_attr_in_voltage0_calibscale_calibration.dev_attr.attr, - NULL, -}; - -static const struct attribute_group ad7746_attribute_group = { - .attrs = ad7746_attributes, -}; - -static int ad7746_write_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int val, - int val2, - long mask) -{ - struct ad7746_chip_info *chip = iio_priv(indio_dev); - int ret, reg; - - switch (mask) { - case IIO_CHAN_INFO_CALIBSCALE: - if (val != 1) - return -EINVAL; - - val = (val2 * 1024) / 15625; - - switch (chan->type) { - case IIO_CAPACITANCE: - reg = AD7746_REG_CAP_GAINH; - break; - case IIO_VOLTAGE: - reg = AD7746_REG_VOLT_GAINH; - break; - default: - return -EINVAL; - } - - mutex_lock(&chip->lock); - ret = i2c_smbus_write_word_swapped(chip->client, reg, val); - mutex_unlock(&chip->lock); - if (ret < 0) - return ret; - - return 0; - case IIO_CHAN_INFO_CALIBBIAS: - if (val < 0 || val > 0xFFFF) - return -EINVAL; - - mutex_lock(&chip->lock); - ret = i2c_smbus_write_word_swapped(chip->client, - AD7746_REG_CAP_OFFH, val); - mutex_unlock(&chip->lock); - if (ret < 0) - return ret; - - return 0; - case IIO_CHAN_INFO_OFFSET: - case IIO_CHAN_INFO_INPUTOFFSET: - if (val < 0 || val > 43008000) /* 21pF */ - return -EINVAL; - - /* - * CAPDAC Scale = 21pF_typ / 127 - * CIN Scale = 8.192pF / 2^24 - * Offset Scale = CAPDAC Scale / CIN Scale = 338646 - */ - - val /= 338646; - mutex_lock(&chip->lock); - chip->capdac[chan->channel][chan->differential] = val > 0 ? - FIELD_PREP(AD7746_CAPDAC_DACP_MASK, val) | AD7746_CAPDAC_DACEN : 0; - - ret = ad7746_set_capdac(chip, chan->channel); - if (ret < 0) { - mutex_unlock(&chip->lock); - return ret; - } - - chip->capdac_set = chan->channel; - mutex_unlock(&chip->lock); - - return 0; - case IIO_CHAN_INFO_SAMP_FREQ: - if (val2) - return -EINVAL; - - switch (chan->type) { - case IIO_CAPACITANCE: - mutex_lock(&chip->lock); - ret = ad7746_store_cap_filter_rate_setup(chip, val); - mutex_unlock(&chip->lock); - return ret; - case IIO_VOLTAGE: - mutex_lock(&chip->lock); - ret = ad7746_store_vt_filter_rate_setup(chip, val); - mutex_unlock(&chip->lock); - return ret; - default: - return -EINVAL; - } - default: - return -EINVAL; - } -} - -static const int ad7746_v_samp_freq[] = { 50, 31, 16, 8, }; -static const int ad7746_cap_samp_freq[] = { 91, 84, 50, 26, 16, 13, 11, 9, }; - -static int ad7746_read_avail(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, const int **vals, - int *type, int *length, long mask) -{ - if (mask != IIO_CHAN_INFO_SAMP_FREQ) - return -EINVAL; - - switch (chan->type) { - case IIO_VOLTAGE: - *vals = ad7746_v_samp_freq; - *length = ARRAY_SIZE(ad7746_v_samp_freq); - break; - case IIO_CAPACITANCE: - *vals = ad7746_cap_samp_freq; - *length = ARRAY_SIZE(ad7746_cap_samp_freq); - break; - default: - return -EINVAL; - } - *type = IIO_VAL_INT; - return IIO_AVAIL_LIST; -} - -static int ad7746_read_channel(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int *val) -{ - struct ad7746_chip_info *chip = iio_priv(indio_dev); - int ret, delay; - u8 data[3]; - u8 regval; - - ret = ad7746_select_channel(indio_dev, chan); - if (ret < 0) - return ret; - delay = ret; - - regval = chip->config | FIELD_PREP(AD7746_CONF_MODE_MASK, - AD7746_CONF_MODE_SINGLE_CONV); - ret = i2c_smbus_write_byte_data(chip->client, AD7746_REG_CFG, regval); - if (ret < 0) - return ret; - - msleep(delay); - /* Now read the actual register */ - ret = i2c_smbus_read_i2c_block_data(chip->client, - ad7746_chan_info[chan->address].addr, - 3, data); - if (ret < 0) - return ret; - - /* - * Offset applied internally becaue the _offset userspace interface is - * needed for the CAP DACs which apply a controllable offset. - */ - *val = get_unaligned_be24(data) - 0x800000; - - return 0; -} - -static int ad7746_read_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - int *val, int *val2, - long mask) -{ - struct ad7746_chip_info *chip = iio_priv(indio_dev); - int ret, idx; - u8 reg; - - switch (mask) { - case IIO_CHAN_INFO_RAW: - mutex_lock(&chip->lock); - ret = ad7746_read_channel(indio_dev, chan, val); - mutex_unlock(&chip->lock); - if (ret < 0) - return ret; - - return IIO_VAL_INT; - case IIO_CHAN_INFO_CALIBSCALE: - switch (chan->type) { - case IIO_CAPACITANCE: - reg = AD7746_REG_CAP_GAINH; - break; - case IIO_VOLTAGE: - reg = AD7746_REG_VOLT_GAINH; - break; - default: - return -EINVAL; - } - - mutex_lock(&chip->lock); - ret = i2c_smbus_read_word_swapped(chip->client, reg); - mutex_unlock(&chip->lock); - if (ret < 0) - return ret; - /* 1 + gain_val / 2^16 */ - *val = 1; - *val2 = (15625 * ret) / 1024; - - return IIO_VAL_INT_PLUS_MICRO; - case IIO_CHAN_INFO_CALIBBIAS: - mutex_lock(&chip->lock); - ret = i2c_smbus_read_word_swapped(chip->client, - AD7746_REG_CAP_OFFH); - mutex_unlock(&chip->lock); - if (ret < 0) - return ret; - *val = ret; - - return IIO_VAL_INT; - case IIO_CHAN_INFO_OFFSET: - case IIO_CHAN_INFO_INPUTOFFSET: - *val = FIELD_GET(AD7746_CAPDAC_DACP_MASK, - chip->capdac[chan->channel][chan->differential]) * 338646; - - return IIO_VAL_INT; - case IIO_CHAN_INFO_SCALE: - switch (chan->type) { - case IIO_CAPACITANCE: - /* 8.192pf / 2^24 */ - *val = 0; - *val2 = 488; - return IIO_VAL_INT_PLUS_NANO; - case IIO_VOLTAGE: - /* 1170mV / 2^23 */ - *val = 1170; - if (chan->channel == 1) - *val *= 6; - *val2 = 23; - return IIO_VAL_FRACTIONAL_LOG2; - case IIO_TEMP: - *val = 125; - *val2 = 8; - return IIO_VAL_FRACTIONAL_LOG2; - default: - return -EINVAL; - } - case IIO_CHAN_INFO_SAMP_FREQ: - switch (chan->type) { - case IIO_CAPACITANCE: - idx = FIELD_GET(AD7746_CONF_CAPFS_MASK, chip->config); - *val = ad7746_cap_filter_rate_table[idx][0]; - return IIO_VAL_INT; - case IIO_VOLTAGE: - idx = FIELD_GET(AD7746_CONF_VTFS_MASK, chip->config); - *val = ad7746_vt_filter_rate_table[idx][0]; - return IIO_VAL_INT; - default: - return -EINVAL; - } - default: - return -EINVAL; - } -} - -static const struct iio_info ad7746_info = { - .attrs = &ad7746_attribute_group, - .read_raw = ad7746_read_raw, - .read_avail = ad7746_read_avail, - .write_raw = ad7746_write_raw, -}; - -static int ad7746_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct device *dev = &client->dev; - struct ad7746_chip_info *chip; - struct iio_dev *indio_dev; - unsigned char regval = 0; - unsigned int vdd_permille; - int ret; - - indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*chip)); - if (!indio_dev) - return -ENOMEM; - - chip = iio_priv(indio_dev); - mutex_init(&chip->lock); - - chip->client = client; - chip->capdac_set = -1; - - indio_dev->name = id->name; - indio_dev->info = &ad7746_info; - indio_dev->channels = ad7746_channels; - if (id->driver_data == 7746) - indio_dev->num_channels = ARRAY_SIZE(ad7746_channels); - else - indio_dev->num_channels = ARRAY_SIZE(ad7746_channels) - 2; - indio_dev->modes = INDIO_DIRECT_MODE; - - if (device_property_read_bool(dev, "adi,exca-output-en")) { - if (device_property_read_bool(dev, "adi,exca-output-invert")) - regval |= AD7746_EXCSETUP_NEXCA; - else - regval |= AD7746_EXCSETUP_EXCA; - } - - if (device_property_read_bool(dev, "adi,excb-output-en")) { - if (device_property_read_bool(dev, "adi,excb-output-invert")) - regval |= AD7746_EXCSETUP_NEXCB; - else - regval |= AD7746_EXCSETUP_EXCB; - } - - ret = device_property_read_u32(dev, "adi,excitation-vdd-permille", - &vdd_permille); - if (!ret) { - switch (vdd_permille) { - case 125: - regval |= FIELD_PREP(AD7746_EXCSETUP_EXCLVL_MASK, 0); - break; - case 250: - regval |= FIELD_PREP(AD7746_EXCSETUP_EXCLVL_MASK, 1); - break; - case 375: - regval |= FIELD_PREP(AD7746_EXCSETUP_EXCLVL_MASK, 2); - break; - case 500: - regval |= FIELD_PREP(AD7746_EXCSETUP_EXCLVL_MASK, 3); - break; - default: - break; - } - } - - ret = i2c_smbus_write_byte_data(chip->client, AD7746_REG_EXC_SETUP, - regval); - if (ret < 0) - return ret; - - return devm_iio_device_register(indio_dev->dev.parent, indio_dev); -} - -static const struct i2c_device_id ad7746_id[] = { - { "ad7745", 7745 }, - { "ad7746", 7746 }, - { "ad7747", 7747 }, - {} -}; -MODULE_DEVICE_TABLE(i2c, ad7746_id); - -static const struct of_device_id ad7746_of_match[] = { - { .compatible = "adi,ad7745" }, - { .compatible = "adi,ad7746" }, - { .compatible = "adi,ad7747" }, - { }, -}; -MODULE_DEVICE_TABLE(of, ad7746_of_match); - -static struct i2c_driver ad7746_driver = { - .driver = { - .name = KBUILD_MODNAME, - .of_match_table = ad7746_of_match, - }, - .probe = ad7746_probe, - .id_table = ad7746_id, -}; -module_i2c_driver(ad7746_driver); - -MODULE_AUTHOR("Michael Hennerich "); -MODULE_DESCRIPTION("Analog Devices AD7746/5/7 capacitive sensor driver"); -MODULE_LICENSE("GPL v2"); From patchwork Mon Apr 18 19:29:07 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonathan Cameron X-Patchwork-Id: 12817074 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id AE271C433FE for ; Mon, 18 Apr 2022 19:21:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1347657AbiDRTY1 (ORCPT ); Mon, 18 Apr 2022 15:24:27 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44860 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1347660AbiDRTY0 (ORCPT ); Mon, 18 Apr 2022 15:24:26 -0400 Received: from ams.source.kernel.org (ams.source.kernel.org [145.40.68.75]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B90CA35A86 for ; Mon, 18 Apr 2022 12:21:45 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id 4BD6BB81087 for ; Mon, 18 Apr 2022 19:21:44 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id A59E6C385AA; Mon, 18 Apr 2022 19:21:41 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1650309703; bh=d9VcXHeNMTW7UhFtf3mV5yYNNpwl04CjkoasMIT6srU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=mj6Wh9oj4tpxSfbL5Vfokyj54j52M+WZyETawpGegcTaT4izqmPjfGXaO4OKfLEES o9vYYI0I1vnvyFUR/C7GKdPXdEnOcCJYVz5BZFkPocxEcICM/0gIour+yjYwvytFaf bVuKWEIoC5n17gaCF3YL3wluom8yzhp52uJCCfInCj5qR/o82MrQlFaDsltAgbso2Z tG12KaOroJfWkRzdmY8oFacgavtAK2i+wXv9D4B7JZ481v2Dpq1WdJIePGlaviUcUv nqxVhy5G27Z98wdmumy+Rt9gOVV4CPP/VzRu/hidUF1zHUAeV/P4nkSKgltHfbE181 d3+D+0+Wt8Pbg== From: Jonathan Cameron To: linux-iio@vger.kernel.org Cc: Michael Hennerich , Lars-Peter Clausen , Vincent Whitchurch , Jonathan Cameron Subject: [PATCH 17/17] RFC: iio: cdc: ad7746: Add roadtest Date: Mon, 18 Apr 2022 20:29:07 +0100 Message-Id: <20220418192907.763933-18-jic23@kernel.org> X-Mailer: git-send-email 2.35.3 In-Reply-To: <20220418192907.763933-1-jic23@kernel.org> References: <20220418192907.763933-1-jic23@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org From: Jonathan Cameron The recent work to cleanup and migrate this driver out of staging relied on using roadtest to verify that the various refactoring and fixes did not cause any regressions. Note I am far from an experienced python coder so a large part of this exercise was to establish if roadtest was useful / usable without that particular skill set. Conclusion yes it is :) Apologies for the code! Signed-off-by: Jonathan Cameron --- .../roadtest/tests/iio/cdc/__init__.py | 0 .../roadtest/roadtest/tests/iio/cdc/config | 1 + .../roadtest/tests/iio/cdc/test_ad7746.py | 323 ++++++++++++++++++ 3 files changed, 324 insertions(+) diff --git a/tools/testing/roadtest/roadtest/tests/iio/cdc/__init__.py b/tools/testing/roadtest/roadtest/tests/iio/cdc/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/tools/testing/roadtest/roadtest/tests/iio/cdc/config b/tools/testing/roadtest/roadtest/tests/iio/cdc/config new file mode 100644 index 000000000000..6e9397325918 --- /dev/null +++ b/tools/testing/roadtest/roadtest/tests/iio/cdc/config @@ -0,0 +1 @@ +CONFIG_AD7746=m diff --git a/tools/testing/roadtest/roadtest/tests/iio/cdc/test_ad7746.py b/tools/testing/roadtest/roadtest/tests/iio/cdc/test_ad7746.py new file mode 100644 index 000000000000..60d75c0f4fe8 --- /dev/null +++ b/tools/testing/roadtest/roadtest/tests/iio/cdc/test_ad7746.py @@ -0,0 +1,323 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Based on test_vncl4010 Copyright Axis Communications AB +# TODO +# - Test read temperatures +# - Test read capacitance +# + +from typing import Any, Final + +from roadtest.backend.i2c import SMBusModel +from roadtest.core.devicetree import DtFragment, DtVar +from roadtest.core.hardware import Hardware +from roadtest.core.suite import UMLTestCase +from roadtest.core.modules import insmod, rmmod +from roadtest.core.sysfs import ( + I2CDriver, + read_float, + read_int, + read_str, + write_int, + write_str, +) + +REG_STATUS: Final = 0x00 +REG_CAP_DATA_H: Final = 0x01 +REG_CAP_DATA_M: Final = 0x02 +REG_CAP_DATA_L: Final = 0x03 +REG_VT_DATA_H: Final = 0x04 +REG_VT_DATA_M: Final = 0x05 +REG_VT_DATA_L: Final = 0x06 +REG_CAP_SETUP: Final = 0x07 +REG_VT_SETUP: Final = 0x08 +REG_EXC_SETUP: Final = 0x09 +REG_CONFIG: Final = 0x0a +REG_CAP_DAC_A: Final = 0x0b +REG_CAP_DAC_B: Final = 0x0c +REG_CAP_OFFSET_H: Final = 0x0d +REG_CAP_OFFSET_L: Final = 0x0e +REG_CAP_GAIN_H: Final = 0x0f +REG_CAP_GAIN_L: Final = 0x10 +REG_VOLT_GAIN_H: Final = 0x11 +REG_VOLT_GAIN_L: Final = 0x12 + +class AD7746(SMBusModel): + def __init__(self, **kwargs: Any) -> None: + super().__init__(regbytes=1, **kwargs) + self.regs = { + REG_STATUS: 0x07, + REG_CAP_DATA_H: 0x00, + REG_CAP_DATA_M: 0x00, + REG_CAP_DATA_L: 0x00, + REG_VT_DATA_H: 0x00, + REG_VT_DATA_M: 0x00, + REG_VT_DATA_L: 0x00, + REG_CAP_SETUP: 0x00, + REG_VT_SETUP: 0x00, + REG_EXC_SETUP: 0x03, + REG_CONFIG: 0xa0, + REG_CAP_DAC_A: 0x00, + REG_CAP_DAC_B: 0x00, + REG_CAP_OFFSET_H: 0x80, + REG_CAP_OFFSET_L: 0x00, + REG_CAP_GAIN_H: 0x00, + REG_CAP_GAIN_L: 0x00, + REG_VOLT_GAIN_H: 0x00, + REG_VOLT_GAIN_L: 0x00, + } + + def reg_read(self, addr: int) -> int: + val = self.regs[addr] + return val; + + def reg_write(self, addr: int, val: int) -> None: + assert addr in self.regs + assert addr not in ( REG_STATUS, + REG_CAP_DATA_H, REG_CAP_DATA_M, REG_CAP_DATA_L, + REG_VT_DATA_H, REG_VT_DATA_M, REG_VT_DATA_L ) + + self.regs[addr] = val + + def inject(self, addr: int, val: int, mask : int = ~0) -> None: + old = self.regs[addr] & ~mask + new = old | (val & mask) + self.regs[addr] = new + +class TestAD7746(UMLTestCase): + dts = DtFragment( + src=""" +&i2c { + cdc@$addr$ { + compatible = "adi,ad7746"; + reg = <0x$addr$>; + }; +}; + """, + variables={ + "addr": DtVar.I2C_ADDR, + }, + ) + + @classmethod + def setUpClass(cls) -> None: + insmod("ad7746") + + @classmethod + def tearDownClass(cls) -> None: + rmmod("ad7746") + + def setUp(self) -> None: + self.driver = I2CDriver("ad7746") + self.hw = Hardware("i2c") + self.hw.load_model(AD7746) + + def tearDown(self) -> None: + self.hw.close() + + def read_attr(self, dev, type, attr, index, extend_name=None, default_val=0) -> float: + name_start = "iio:device0/in_" + type; + if extend_name is None: + try: + scale = read_float(dev.path / (name_start + str(index) + "_" + attr)) + except: + try: + scale = read_float(dev.path / (name_start + "_" + attr)) + except: + scale = default_val + if extend_name is not None: + try: + scale = read_float(dev.path / (name_start + str(index) + "_" + extend_name + "_" + attr)) + except: + try: + scale = read_float(dev.path / (name_start + str(index) + "_" + attr)) + except: + try: + scale = read_float(dev.path / (name_start + "_" + attr)) + except: + scale = default_val + + return scale + + def test_scales(self) -> None: + with self.driver.bind(self.dts["addr"]) as dev: + scale = self.read_attr(dev, "voltage", "scale", 0, default_val=1.0) + self.assertAlmostEqual(scale, 1170 / (1 << 23)) + scale = self.read_attr(dev, "voltage", "scale", 1, "supply", default_val=1.0) + self.assertAlmostEqual(scale, 1170 * 6 / ( 1 << 23)) + scale = self.read_attr(dev, "capacitance", "scale", 0, default_val=1.0) + self.assertEqual(scale, 0.000000488) + + def test_read_avail(self) -> None: + with self.driver.bind(self.dts["addr"]) as dev: + test = read_str(dev.path / "iio:device0/in_capacitance_sampling_frequency_available") + assert test == "91 84 50 26 16 13 11 9" + test = read_str(dev.path / "iio:device0/in_voltage_sampling_frequency_available") + assert test == "50 31 16 8", test + + def test_read_channels(self) -> None: + with self.driver.bind(self.dts["addr"]) as dev: + testscale = 1170.0 / (1 << 23) + # Test endpoints and each of the bytes + testvals = (( 0x0, 0x0, 0x0, (-0x800000) * testscale), + ( 0x0, 0x40, 0x0, (-0x800000 + 0x004000) * testscale), + ( 0x80, 0x0, 0x0, (0x0) * testscale), + ( 0x80, 0x0, 0x1, (0x1) * testscale), + ( 0xff, 0xff, 0xff, (0x0 + 0x7fffff) * testscale), + ) + scale = self.read_attr(dev, "voltage", "scale", 0, default_val=1.0) + offset = self.read_attr(dev, "voltage", "offset", 0, default_val=0.0) + + # Should really be testing that the voltage after application of + # scale and offset is correct, not raw values. + for h, m, l, testval in testvals: + # Sequence matters as we will only write registers if the change. + # Hence always proceed a vt read with a cap read and visa versa + read_int(dev.path / "iio:device0/in_capacitance0_raw") + # value is 24 bit and driver offsets it by -0x800000. + self.hw.inject(REG_VT_DATA_H, h) + self.hw.inject(REG_VT_DATA_M, m) + self.hw.inject(REG_VT_DATA_L, l) + value = read_int(dev.path / "iio:device0/in_voltage0_raw") + self.assertAlmostEqual((value + offset) * scale, testval, 4) + mock = self.hw.update_mock() + mock.assert_last_reg_write(self, REG_VT_SETUP, 0x80 | 0x60) + #verify capacitance read disabled + cap_setup = mock.get_last_reg_write(REG_CAP_SETUP) + assert(not (cap_setup & 0x80)) + mock.reset_mock() + testscale = 1170 * 6 / (1 << 23) + # Test endpoints and each of the bytes + testvals = (( 0x0, 0x0, 0x0, (-0x800000) * testscale), + ( 0x0, 0x40, 0x0, (-0x800000 + 0x004000) * testscale), + ( 0x80, 0x0, 0x0, (0x0) * testscale), + ( 0x80, 0x0, 0x1, (0x1) * testscale), + ( 0xff, 0xff, 0xff, (0x0 + 0x7fffff) * testscale), + ) + scale = self.read_attr(dev, "voltage", "scale", 1, "supply", default_val = 1.0) + for h, m, l, testval in testvals: + read_int(dev.path / "iio:device0/in_capacitance0_raw") + self.hw.inject(REG_VT_DATA_H, h) + self.hw.inject(REG_VT_DATA_M, m) + self.hw.inject(REG_VT_DATA_L, l) + value = read_int(dev.path/ "iio:device0/in_voltage1_supply_raw") + # Supply voltage channel is attenuated by x6 + self.assertAlmostEqual((value + offset) * scale, testval, 4) + mock = self.hw.update_mock() + mock.assert_last_reg_write(self, REG_VT_SETUP, 0x80 | 0x40) + #verify capacitance read disabled + cap_setup = mock.get_last_reg_write(REG_CAP_SETUP) + assert(not (cap_setup & 0x80)) + mock.reset_mock() + + # Only bother testing one of the temperature channels. They are very similar. + testvals = (( 0x0, 0x0, 0x0, (0/2048.0 - 4096) * 1000), + ( 0x0, 0x40, 0x0, (0x004000/2048.0 - 4096) * 1000), + ( 0x80, 0x0, 0x0, (0x800000/2048.0 - 4096) * 1000), + ( 0x80, 0x0, 0x1, (0x800001/2048.0 - 4096) * 1000), + ( 0xff, 0xff, 0xff, (0xffffff/2048.0 - 4096) * 1000), + ) + scale = self.read_attr(dev, "temp", "scale", 0, default_val = 1.0) + for h, m, l, testval in testvals: + read_int(dev.path / "iio:device0/in_capacitance0_raw") + self.hw.inject(REG_VT_DATA_H, h) + self.hw.inject(REG_VT_DATA_M, m) + self.hw.inject(REG_VT_DATA_L, l) + value = read_int(dev.path/ "iio:device0/in_temp0_raw") + self.assertAlmostEqual(value * scale, testval, 4) + mock = self.hw.update_mock() + mock.assert_last_reg_write(self, REG_VT_SETUP, 0x80 | 0x00) + #verify capacitance read disabled + cap_setup = mock.get_last_reg_write(REG_CAP_SETUP) + assert(not (cap_setup & 0x80)) + mock.reset_mock() + + testscale = 0.000000488 + # Test endpoints and each of the bytes + testvals = (( 0x0, 0x0, 0x0, (-0x800000) * testscale), + ( 0x0, 0x40, 0x0, (-0x800000 + 0x004000) * testscale), + ( 0x80, 0x0, 0x0, (0x0) * testscale), + ( 0x80, 0x0, 0x1, (0x1) * testscale), + ( 0xff, 0xff, 0xff, (0x0 + 0x7fffff) * testscale), + ) + + scale = self.read_attr(dev, "capacitance", "scale", 0, default_val=1.0) + offset = 0.0 #self.read_attr(dev, "capacitance", "offset", 0, default_val=0.0) + + # Should really be testing that the voltage after application of + # scale and offset is correct, not raw values. + for h, m, l, testval in testvals: + # Sequence matters as we will only write registers if the change. + # Hence always proceed a vt read with a cap read and visa versa + read_int(dev.path / "iio:device0/in_voltage0_raw") + # value is 24 bit and driver offsets it by -0x800000. + self.hw.inject(REG_CAP_DATA_H, h) + self.hw.inject(REG_CAP_DATA_M, m) + self.hw.inject(REG_CAP_DATA_L, l) + value = read_int(dev.path / "iio:device0/in_capacitance0_raw") + self.assertAlmostEqual((value + offset) * scale, testval, 9) + mock = self.hw.update_mock() + mock.assert_last_reg_write(self, REG_CAP_SETUP, 0x80) + #verify capacitance read disabled + vt_setup = mock.get_last_reg_write(REG_VT_SETUP) + assert(not (vt_setup & 0x80)) + mock.reset_mock() + + scale = self.read_attr(dev, "capacitance", "scale", 1, default_val=1.0) + offset = 0.0 #self.read_attr(dev, "capacitance", "offset", 0, default_val=0.0) + + # Should really be testing that the voltage after application of + # scale and offset is correct, not raw values. + for h, m, l, testval in testvals: + # Sequence matters as we will only write registers if the change. + # Hence always proceed a vt read with a cap read and visa versa + read_int(dev.path / "iio:device0/in_voltage0_raw") + # value is 24 bit and driver offsets it by -0x800000. + self.hw.inject(REG_CAP_DATA_H, h) + self.hw.inject(REG_CAP_DATA_M, m) + self.hw.inject(REG_CAP_DATA_L, l) + value = read_int(dev.path / "iio:device0/in_capacitance1_raw") + self.assertAlmostEqual((value + offset) * scale, testval, 9) + mock = self.hw.update_mock() + mock.assert_last_reg_write(self, REG_CAP_SETUP, 0x80 | 0x40) + #verify capacitance read disabled + vt_setup = mock.get_last_reg_write(REG_VT_SETUP) + assert(not (vt_setup & 0x80)) + mock.reset_mock() + + # Should really be testing that the voltage after application of + # scale and offset is correct, not raw values. + for h, m, l, testval in testvals: + # Sequence matters as we will only write registers if the change. + # Hence always proceed a vt read with a cap read and visa versa + read_int(dev.path / "iio:device0/in_voltage0_raw") + # value is 24 bit and driver offsets it by -0x800000. + self.hw.inject(REG_CAP_DATA_H, h) + self.hw.inject(REG_CAP_DATA_M, m) + self.hw.inject(REG_CAP_DATA_L, l) + value = read_int(dev.path / "iio:device0/in_capacitance0-capacitance2_raw") + self.assertAlmostEqual((value + offset) * scale, testval, 9) + mock = self.hw.update_mock() + mock.assert_last_reg_write(self, REG_CAP_SETUP, 0x80 | 0x20) + #verify capacitance read disabled + vt_setup = mock.get_last_reg_write(REG_VT_SETUP) + assert(not (vt_setup & 0x80)) + mock.reset_mock() + + # Should really be testing that the voltage after application of + # scale and offset is correct, not raw values. + for h, m, l, testval in testvals: + # Sequence matters as we will only write registers if the change. + # Hence always proceed a vt read with a cap read and visa versa + read_int(dev.path / "iio:device0/in_voltage0_raw") + # value is 24 bit and driver offsets it by -0x800000. + self.hw.inject(REG_CAP_DATA_H, h) + self.hw.inject(REG_CAP_DATA_M, m) + self.hw.inject(REG_CAP_DATA_L, l) + value = read_int(dev.path / "iio:device0/in_capacitance1-capacitance3_raw") + self.assertAlmostEqual((value + offset) * scale, testval, 9) + mock = self.hw.update_mock() + mock.assert_last_reg_write(self, REG_CAP_SETUP, 0x80 | 0x60) + #verify capacitance read disabled + vt_setup = mock.get_last_reg_write(REG_VT_SETUP) + assert(not (vt_setup & 0x80)) + mock.reset_mock()