From patchwork Wed May 1 14:55:34 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Julien Stephan X-Patchwork-Id: 13650829 Received: from mail-lj1-f179.google.com (mail-lj1-f179.google.com [209.85.208.179]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AF22112F36D for ; Wed, 1 May 2024 14:55:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.179 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714575352; cv=none; b=Dw7nxZ8Q/AzTDFYk21CpE1DK2N8Nnkl1IZtta7MyqdAaYhEqY0fWz6Rc0PIrtng2n2qui55HRUa0XWMND6EsWp1Zji57x2i9u3pHcYOE9VXls1S0SaLYb4fb52FL9ix9aFdh3TFu2fOeUoL0UuDkLtibXC6SIoV7SFerUnqwFhA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714575352; c=relaxed/simple; bh=IDhrjIJtC1G3o2fCZqsHvxz7NEDrI0F5jKU0EEQs398=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=UXowGhCDCdkC49QNAs2O+xv7cVHBwMxnCbOSiWFw3ODXVcvEBwSRCXh1SvjgH5zvxfB+jnbD7zvlbmNu3s26316jG6hIVPFAGf8BMjyuSB3+kwRrWDbtgJe1af8k9+Ern4Pkhnc/0xNFJsvb4cJhmjQqT9tnaQZhsr8jam/PRIQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=baylibre.com; spf=pass smtp.mailfrom=baylibre.com; dkim=pass (2048-bit key) header.d=baylibre-com.20230601.gappssmtp.com header.i=@baylibre-com.20230601.gappssmtp.com header.b=HZWK5idm; arc=none smtp.client-ip=209.85.208.179 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=baylibre.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=baylibre-com.20230601.gappssmtp.com header.i=@baylibre-com.20230601.gappssmtp.com header.b="HZWK5idm" Received: by mail-lj1-f179.google.com with SMTP id 38308e7fff4ca-2e0a0cc5e83so36883951fa.1 for ; Wed, 01 May 2024 07:55:50 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1714575349; x=1715180149; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=Fhz/hQk8RD1tt0hu/cR4amFoB9mWCchFbN+TxPow/AQ=; b=HZWK5idmP6QILE3q3N3KEcFMgKf6S+NSTqRhw5tSLPSieMEYngUugUXemk6LlhS8Wg hQSkXexZpa8QZiDpL8c0M0QFL7rncNPbbQCmtZQQUq0ou1Lm+e0NrVwVHmgawXzBCWyI hgFNVHVva4xsacW+JUqAtmDKxzAR0EtdTXx83v5ct9TxbEJ5piXUTfNYLlYbeCAV5qn1 OlfD/GT79UAZ9AUBZnNfxahAzN+YaDIFDDUF4e1Zzf6bzzLz3TrNijo+PO1qqxkoHpXD pnSCKiL9/JJ1IAGekKlcwv25fqE19dDWd6GACM6jRN+IYoFydQgUcfZt2GspX20kuS/6 7pFw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1714575349; x=1715180149; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Fhz/hQk8RD1tt0hu/cR4amFoB9mWCchFbN+TxPow/AQ=; b=LhIpPYTNFJKGJmDWsIwfu5zFOoZSxB6XAv056dz8SVJLpGTbctgMR/6h7z7uN0cN0h Z43rpNihOA+CZghNC/G4MrUzp6gMj8HaZERlQmMF7tLw/sr3/1m2jAMvj6aL754tCYH7 M24xj1/glc/u2H7SDSm9PAURh2R6DHoJr3nkE5GX/QoAGyHmLwxRWwr3JmOt3WA1DJB4 Pz5tesgQBJIVX5qu+OBMJu7MMlGmy4L/Ow32uT9SO6UzZHt2slGEthD3okRPez4qwZqu b263DRMpvvSaTLLH4nEcmdSb8M7Mbe2ZmXxe2raD4He5gtPEZeujaYRWYFg5ura7VqvP mFxA== X-Forwarded-Encrypted: i=1; AJvYcCWpj/8xXcXKjMGL3ybibSk+YVM/NhQSlKk+C+Gx6AVcQVE78wCkZrK1zFsRULvKClu/0QgzT0C4idHlVF+ZHBCTrIoO2+v2kywb X-Gm-Message-State: AOJu0YxlEYWmZulEUH8AGnDeHayK8kW2PYn8aMNWL0j8jjaZC33DXqbu Q/qW2LmBEfLMWOAdfZIBZdiZoXLIBg4Q02u/r4jucAbp5k5eaOQ+TiiJM6Gnjhs= X-Google-Smtp-Source: AGHT+IExWbzFu/y+P/BHymNniS1NWoawv6PjReU8jo15sbOyMVB1Zznn6zp0RVZFa5o0QkTLX+GZDA== X-Received: by 2002:a05:651c:222:b0:2d8:930c:bbfa with SMTP id z2-20020a05651c022200b002d8930cbbfamr1798566ljn.5.1714575348754; Wed, 01 May 2024 07:55:48 -0700 (PDT) Received: from [192.168.1.61] ([2a02:842a:d52e:6101:6fd0:6c4:5d68:f0a5]) by smtp.gmail.com with ESMTPSA id o27-20020a05600c511b00b00418a386c17bsm2422999wms.12.2024.05.01.07.55.48 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 01 May 2024 07:55:48 -0700 (PDT) From: Julien Stephan Date: Wed, 01 May 2024 16:55:34 +0200 Subject: [PATCH RFC v6 01/10] dt-bindings: iio: adc: Add binding for AD7380 ADCs Precedence: bulk X-Mailing-List: linux-iio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20240501-adding-new-ad738x-driver-v6-1-3c0741154728@baylibre.com> References: <20240501-adding-new-ad738x-driver-v6-0-3c0741154728@baylibre.com> In-Reply-To: <20240501-adding-new-ad738x-driver-v6-0-3c0741154728@baylibre.com> To: Lars-Peter Clausen , Michael Hennerich , =?utf-8?q?Nuno_S=C3=A1?= , David Lechner , Jonathan Cameron , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Liam Girdwood , Mark Brown Cc: kernel test robot , linux-iio@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Julien Stephan , Conor Dooley X-Mailer: b4 0.13.0 From: David Lechner This adds a binding specification for the Analog Devices Inc. AD7380 family of ADCs. Signed-off-by: David Lechner Signed-off-by: Julien Stephan Reviewed-by: Conor Dooley --- .../devicetree/bindings/iio/adc/adi,ad7380.yaml | 82 ++++++++++++++++++++++ MAINTAINERS | 9 +++ 2 files changed, 91 insertions(+) diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad7380.yaml b/Documentation/devicetree/bindings/iio/adc/adi,ad7380.yaml new file mode 100644 index 000000000000..5e1ee0ebe0a2 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/adc/adi,ad7380.yaml @@ -0,0 +1,82 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/adc/adi,ad7380.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Analog Devices Simultaneous Sampling Analog to Digital Converters + +maintainers: + - Michael Hennerich + - Nuno Sá + +description: | + * https://www.analog.com/en/products/ad7380.html + * https://www.analog.com/en/products/ad7381.html + +$ref: /schemas/spi/spi-peripheral-props.yaml# + +properties: + compatible: + enum: + - adi,ad7380 + - adi,ad7381 + + reg: + maxItems: 1 + + spi-max-frequency: + maximum: 80000000 + spi-cpol: true + spi-cpha: true + + vcc-supply: + description: A 3V to 3.6V supply that powers the chip. + + vlogic-supply: + description: + A 1.65V to 3.6V supply for the logic pins. + + refio-supply: + description: + A 2.5V to 3.3V supply for the external reference voltage. When omitted, + the internal 2.5V reference is used. + + interrupts: + description: + When the device is using 1-wire mode, this property is used to optionally + specify the ALERT interrupt. + maxItems: 1 + +required: + - compatible + - reg + - vcc-supply + - vlogic-supply + +unevaluatedProperties: false + +examples: + - | + #include + + spi { + #address-cells = <1>; + #size-cells = <0>; + + adc@0 { + compatible = "adi,ad7380"; + reg = <0>; + + spi-cpol; + spi-cpha; + spi-max-frequency = <80000000>; + + interrupts = <27 IRQ_TYPE_EDGE_FALLING>; + interrupt-parent = <&gpio0>; + + vcc-supply = <&supply_3_3V>; + vlogic-supply = <&supply_3_3V>; + refio-supply = <&supply_2_5V>; + }; + }; diff --git a/MAINTAINERS b/MAINTAINERS index 8ad79cf70552..5bb168937853 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -427,6 +427,15 @@ W: http://wiki.analog.com/AD7142 W: https://ez.analog.com/linux-software-drivers F: drivers/input/misc/ad714x.c +AD738X ADC DRIVER (AD7380/1/2/4) +M: Michael Hennerich +M: Nuno Sá +R: David Lechner +S: Supported +W: https://wiki.analog.com/resources/tools-software/linux-drivers/iio-adc/ad738x +W: https://ez.analog.com/linux-software-drivers +F: Documentation/devicetree/bindings/iio/adc/adi,ad7380.yaml + AD7877 TOUCHSCREEN DRIVER M: Michael Hennerich S: Supported From patchwork Wed May 1 14:55:35 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Julien Stephan X-Patchwork-Id: 13650832 Received: from mail-lj1-f178.google.com (mail-lj1-f178.google.com [209.85.208.178]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4869A12F373 for ; Wed, 1 May 2024 14:55:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.178 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714575356; cv=none; b=u/D02wmFEivC7CUb82MxCOBi7F1Tq7tgM2FUYinmo0Sh5s1w/hQ0FnaNX43XzP3HYPMgWArPFK2KihhJO6eazRDMdMrWbdje+u0a3g14AHQNBhfYUQ8DMjG157bt6BKknGRllbCry/UTkd4KX5/rk3mWb9sOo8jZRto8IGwUZ/I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714575356; c=relaxed/simple; bh=MBENGPPqyNcE3f0Eq4rYojKREBiI6HECbglfQTnhvc8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=ClZZUDSsiYdUjfAQd2ICYY7+T3cvkSQ4P+dvXUCsA0aB3Nu462QN2VipNQX49u++lLHRXEID4I/XwZswl1697OY32IgqL+0z7JHae0LEvjP0SDugFoN1uCx20U/Gk8V13oNNBYF7j1i6Wit7XljpUzQ5S/6qXL5iQJmh+Icl6yQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=baylibre.com; spf=pass smtp.mailfrom=baylibre.com; dkim=pass (2048-bit key) header.d=baylibre-com.20230601.gappssmtp.com header.i=@baylibre-com.20230601.gappssmtp.com header.b=m8r06lJ1; arc=none smtp.client-ip=209.85.208.178 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=baylibre.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=baylibre-com.20230601.gappssmtp.com header.i=@baylibre-com.20230601.gappssmtp.com header.b="m8r06lJ1" Received: by mail-lj1-f178.google.com with SMTP id 38308e7fff4ca-2d8a24f8a3cso84812921fa.1 for ; Wed, 01 May 2024 07:55:53 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1714575351; x=1715180151; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=SqLntdBdXYRYi9ks5TlMm8Ua5AzpqigLpD/dxKZjzhw=; b=m8r06lJ1Pdwirv47bz5DXUdVlZIJXpUDCxe+JN5JPcbRTIOhsGJyZe/UYWp30oHBII /mj2VkMxzbYHy72WojL0GlrZ1N7iX0P6hB7Vfms/Uln4oVbXyuEAXlcVkIfViQp7f03f KCgXgD/zC4XSQ3fvCbGYLxFeLRgACOoGL4zXnQZ/jv3AK/8fsxSexfrXaeqmgBdqJ7NM yVTopOsq6+TagqYknckuviDXyoOSI7D9NuTii20K3RTY2o9JcWEZANWcxs8z3EHoiLMv h/bxKgNhvwcsl+KitTliUJcFd/QFBRxggn38738Di3xAF8rb9WUngzHplXWHGhl8Zfcx Us6Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1714575351; x=1715180151; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=SqLntdBdXYRYi9ks5TlMm8Ua5AzpqigLpD/dxKZjzhw=; b=VXrQg6MpNk90Q9iEatLnrsnFtHH2+TgBlpuYfBbzvHgw1mxrvOunGMxQ2MDjSfLEZu ASpV1DU20qEpZjRjOfardMUrpSdK2Ocx1PKfE+4m0FLpryfNhz8jNtsrt4EHiX4ed/0R zudXG4Q5dBdOQjH+SDHVXK3PLjihXRdAJiNtmA5O/3M/rd3idUWlE3jXiocF4jhAdbd/ 3ShZp3YQC5VwyZg7iXD3oOOy28BoLrvYBLF0wwftHm5Ol5G/AwpFsJKffOY6o2w/fBw3 XHIihhUewwNWlcsrJ0iZL5jPsZF233+/SHoBducxNNfbbvjGzOrgLtE52BW9m5q+o9sO wdjg== X-Forwarded-Encrypted: i=1; AJvYcCWkuTQWbK93MiAFb/mdfRytDd93+DuHpUbsfPRjWSnxfhTuwpaFzt1o7Sso3tkRyPj43hYlrT4jdCG/rK0Nx91bM0l6hlOhSLzb X-Gm-Message-State: AOJu0Ywmwa2GQwQ87RS0ds9WYUyX7sIV6ferBH5ClhmG9lzBYkqHFMdr 0nkPXfd2SR2ChjpRJ9DHnO9q6V7an3Qkv2N9GIE6ajgjWEQHrfXcfK7e+N5iRVM= X-Google-Smtp-Source: AGHT+IE6UO6JMlz9VaZ800sjdNTf6JrX3yjaN+lK78tNrDPOCk5/mp2t3euxDsuNDdBChbGeER9y1Q== X-Received: by 2002:a2e:a7c5:0:b0:2de:7046:b8f8 with SMTP id x5-20020a2ea7c5000000b002de7046b8f8mr2195990ljp.5.1714575349559; Wed, 01 May 2024 07:55:49 -0700 (PDT) Received: from [192.168.1.61] ([2a02:842a:d52e:6101:6fd0:6c4:5d68:f0a5]) by smtp.gmail.com with ESMTPSA id o27-20020a05600c511b00b00418a386c17bsm2422999wms.12.2024.05.01.07.55.48 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 01 May 2024 07:55:49 -0700 (PDT) From: Julien Stephan Date: Wed, 01 May 2024 16:55:35 +0200 Subject: [PATCH RFC v6 02/10] iio: adc: ad7380: new driver for AD7380 ADCs Precedence: bulk X-Mailing-List: linux-iio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20240501-adding-new-ad738x-driver-v6-2-3c0741154728@baylibre.com> References: <20240501-adding-new-ad738x-driver-v6-0-3c0741154728@baylibre.com> In-Reply-To: <20240501-adding-new-ad738x-driver-v6-0-3c0741154728@baylibre.com> To: Lars-Peter Clausen , Michael Hennerich , =?utf-8?q?Nuno_S=C3=A1?= , David Lechner , Jonathan Cameron , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Liam Girdwood , Mark Brown Cc: kernel test robot , linux-iio@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Julien Stephan , Stefan Popa X-Mailer: b4 0.13.0 From: David Lechner This adds a new driver for the AD7380 family ADCs. The driver currently implements basic support for the AD7380, AD7381, 2-channel differential ADCs. Support for additional single-ended, pseudo-differential and 4-channel chips that use the same register map as well as additional features of the chip will be added in future patches. Co-developed-by: Stefan Popa Signed-off-by: Stefan Popa Reviewed-by: Nuno Sa Signed-off-by: David Lechner [Julien Stephan: add datasheet links of supported parts] [Julien Stephan: fix rx/tx buffer for regmap access] [Julien Stephan: fix scale issue] [Julien Stephan: use the new iio_device_claim_direct_scoped instead of iio_device_claim_direct_mode] Signed-off-by: Julien Stephan --- MAINTAINERS | 1 + drivers/iio/adc/Kconfig | 16 ++ drivers/iio/adc/Makefile | 1 + drivers/iio/adc/ad7380.c | 443 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 461 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 5bb168937853..87724a9e9f9f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -435,6 +435,7 @@ S: Supported W: https://wiki.analog.com/resources/tools-software/linux-drivers/iio-adc/ad738x W: https://ez.analog.com/linux-software-drivers F: Documentation/devicetree/bindings/iio/adc/adi,ad7380.yaml +F: drivers/iio/adc/ad7380.c AD7877 TOUCHSCREEN DRIVER M: Michael Hennerich diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index 8db68b80b391..631386b037ae 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -155,6 +155,22 @@ config AD7298 To compile this driver as a module, choose M here: the module will be called ad7298. +config AD7380 + tristate "Analog Devices AD7380 ADC driver" + depends on SPI_MASTER + select IIO_BUFFER + select IIO_TRIGGER + select IIO_TRIGGERED_BUFFER + help + AD7380 is a family of simultaneous sampling ADCs that share the same + SPI register map and have similar pinouts. + + Say yes here to build support for Analog Devices AD7380 ADC and + similar chips. + + To compile this driver as a module, choose M here: the module will be + called ad7380. + config AD7476 tristate "Analog Devices AD7476 1-channel ADCs driver and other similar devices from AD and TI" depends on SPI diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index edb32ce2af02..bd3cbbb178fa 100644 --- a/drivers/iio/adc/Makefile +++ b/drivers/iio/adc/Makefile @@ -19,6 +19,7 @@ obj-$(CONFIG_AD7291) += ad7291.o obj-$(CONFIG_AD7292) += ad7292.o obj-$(CONFIG_AD7298) += ad7298.o obj-$(CONFIG_AD7923) += ad7923.o +obj-$(CONFIG_AD7380) += ad7380.o obj-$(CONFIG_AD7476) += ad7476.o obj-$(CONFIG_AD7606_IFACE_PARALLEL) += ad7606_par.o obj-$(CONFIG_AD7606_IFACE_SPI) += ad7606_spi.o diff --git a/drivers/iio/adc/ad7380.c b/drivers/iio/adc/ad7380.c new file mode 100644 index 000000000000..a218f59c276e --- /dev/null +++ b/drivers/iio/adc/ad7380.c @@ -0,0 +1,443 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Analog Devices AD738x Simultaneous Sampling SAR ADCs + * + * Copyright 2017 Analog Devices Inc. + * Copyright 2024 BayLibre, SAS + * + * Datasheets of supported parts: + * ad7380/1 : https://www.analog.com/media/en/technical-documentation/data-sheets/AD7380-7381.pdf + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +/* 2.5V internal reference voltage */ +#define AD7380_INTERNAL_REF_MV 2500 + +/* reading and writing registers is more reliable at lower than max speed */ +#define AD7380_REG_WR_SPEED_HZ 10000000 + +#define AD7380_REG_WR BIT(15) +#define AD7380_REG_REGADDR GENMASK(14, 12) +#define AD7380_REG_DATA GENMASK(11, 0) + +#define AD7380_REG_ADDR_NOP 0x0 +#define AD7380_REG_ADDR_CONFIG1 0x1 +#define AD7380_REG_ADDR_CONFIG2 0x2 +#define AD7380_REG_ADDR_ALERT 0x3 +#define AD7380_REG_ADDR_ALERT_LOW_TH 0x4 +#define AD7380_REG_ADDR_ALERT_HIGH_TH 0x5 + +#define AD7380_CONFIG1_OS_MODE BIT(9) +#define AD7380_CONFIG1_OSR GENMASK(8, 6) +#define AD7380_CONFIG1_CRC_W BIT(5) +#define AD7380_CONFIG1_CRC_R BIT(4) +#define AD7380_CONFIG1_ALERTEN BIT(3) +#define AD7380_CONFIG1_RES BIT(2) +#define AD7380_CONFIG1_REFSEL BIT(1) +#define AD7380_CONFIG1_PMODE BIT(0) + +#define AD7380_CONFIG2_SDO2 GENMASK(9, 8) +#define AD7380_CONFIG2_SDO BIT(8) +#define AD7380_CONFIG2_RESET GENMASK(7, 0) + +#define AD7380_CONFIG2_RESET_SOFT 0x3C +#define AD7380_CONFIG2_RESET_HARD 0xFF + +#define AD7380_ALERT_LOW_TH GENMASK(11, 0) +#define AD7380_ALERT_HIGH_TH GENMASK(11, 0) + +struct ad7380_chip_info { + const char *name; + const struct iio_chan_spec *channels; + unsigned int num_channels; +}; + +#define AD7380_CHANNEL(index, bits) { \ + .type = IIO_VOLTAGE, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ + .indexed = 1, \ + .differential = 1, \ + .channel = 2 * (index), \ + .channel2 = 2 * (index) + 1, \ + .scan_index = (index), \ + .scan_type = { \ + .sign = 's', \ + .realbits = (bits), \ + .storagebits = 16, \ + .endianness = IIO_CPU, \ + }, \ +} + +#define DEFINE_AD7380_2_CHANNEL(name, bits) \ +static const struct iio_chan_spec name[] = { \ + AD7380_CHANNEL(0, bits), \ + AD7380_CHANNEL(1, bits), \ + IIO_CHAN_SOFT_TIMESTAMP(2), \ +} + +DEFINE_AD7380_2_CHANNEL(ad7380_channels, 16); +DEFINE_AD7380_2_CHANNEL(ad7381_channels, 14); + +/* Since this is simultaneous sampling, we don't allow individual channels. */ +static const unsigned long ad7380_2_channel_scan_masks[] = { + GENMASK(1, 0), + 0 +}; + +static const struct ad7380_chip_info ad7380_chip_info = { + .name = "ad7380", + .channels = ad7380_channels, + .num_channels = ARRAY_SIZE(ad7380_channels), +}; + +static const struct ad7380_chip_info ad7381_chip_info = { + .name = "ad7381", + .channels = ad7381_channels, + .num_channels = ARRAY_SIZE(ad7381_channels), +}; + +struct ad7380_state { + const struct ad7380_chip_info *chip_info; + struct spi_device *spi; + struct regmap *regmap; + unsigned int vref_mv; + /* + * DMA (thus cache coherency maintenance) requires the + * transfer buffers to live in their own cache lines. + * Make the buffer large enough for 2 16-bit samples and one 64-bit + * aligned 64 bit timestamp. + */ + struct { + u16 raw[2]; + + s64 ts __aligned(8); + } scan_data __aligned(IIO_DMA_MINALIGN); + u16 tx; + u16 rx; +}; + +static int ad7380_regmap_reg_write(void *context, unsigned int reg, + unsigned int val) +{ + struct ad7380_state *st = context; + struct spi_transfer xfer = { + .speed_hz = AD7380_REG_WR_SPEED_HZ, + .bits_per_word = 16, + .len = 2, + .tx_buf = &st->tx, + }; + + st->tx = FIELD_PREP(AD7380_REG_WR, 1) | + FIELD_PREP(AD7380_REG_REGADDR, reg) | + FIELD_PREP(AD7380_REG_DATA, val); + + return spi_sync_transfer(st->spi, &xfer, 1); +} + +static int ad7380_regmap_reg_read(void *context, unsigned int reg, + unsigned int *val) +{ + struct ad7380_state *st = context; + struct spi_transfer xfers[] = { + { + .speed_hz = AD7380_REG_WR_SPEED_HZ, + .bits_per_word = 16, + .len = 2, + .tx_buf = &st->tx, + .cs_change = 1, + .cs_change_delay = { + .value = 10, /* t[CSH] */ + .unit = SPI_DELAY_UNIT_NSECS, + }, + }, { + .speed_hz = AD7380_REG_WR_SPEED_HZ, + .bits_per_word = 16, + .len = 2, + .rx_buf = &st->rx, + }, + }; + int ret; + + st->tx = FIELD_PREP(AD7380_REG_WR, 0) | + FIELD_PREP(AD7380_REG_REGADDR, reg) | + FIELD_PREP(AD7380_REG_DATA, 0); + + ret = spi_sync_transfer(st->spi, xfers, ARRAY_SIZE(xfers)); + if (ret < 0) + return ret; + + *val = FIELD_GET(AD7380_REG_DATA, st->rx); + + return 0; +} + +static const struct regmap_config ad7380_regmap_config = { + .reg_bits = 3, + .val_bits = 12, + .reg_read = ad7380_regmap_reg_read, + .reg_write = ad7380_regmap_reg_write, + .max_register = AD7380_REG_ADDR_ALERT_HIGH_TH, + .can_sleep = true, +}; + +static int ad7380_debugfs_reg_access(struct iio_dev *indio_dev, u32 reg, + u32 writeval, u32 *readval) +{ + iio_device_claim_direct_scoped(return -EBUSY, indio_dev) { + struct ad7380_state *st = iio_priv(indio_dev); + int ret; + + if (readval) + ret = regmap_read(st->regmap, reg, readval); + else + ret = regmap_write(st->regmap, reg, writeval); + + return ret; + } + unreachable(); +} + +static irqreturn_t ad7380_trigger_handler(int irq, void *p) +{ + struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + struct ad7380_state *st = iio_priv(indio_dev); + struct spi_transfer xfer = { + .bits_per_word = st->chip_info->channels[0].scan_type.realbits, + .len = 4, + .rx_buf = st->scan_data.raw, + }; + int ret; + + ret = spi_sync_transfer(st->spi, &xfer, 1); + if (ret) + goto out; + + iio_push_to_buffers_with_timestamp(indio_dev, &st->scan_data, + pf->timestamp); + +out: + iio_trigger_notify_done(indio_dev->trig); + + return IRQ_HANDLED; +} + +static int ad7380_read_direct(struct ad7380_state *st, + struct iio_chan_spec const *chan, int *val) +{ + struct spi_transfer xfers[] = { + /* toggle CS (no data xfer) to trigger a conversion */ + { + .speed_hz = AD7380_REG_WR_SPEED_HZ, + .bits_per_word = chan->scan_type.realbits, + .delay = { + .value = 190, /* t[CONVERT] */ + .unit = SPI_DELAY_UNIT_NSECS, + }, + .cs_change = 1, + .cs_change_delay = { + .value = 10, /* t[CSH] */ + .unit = SPI_DELAY_UNIT_NSECS, + }, + }, + /* then read both channels */ + { + .speed_hz = AD7380_REG_WR_SPEED_HZ, + .bits_per_word = chan->scan_type.realbits, + .rx_buf = st->scan_data.raw, + .len = 4, + }, + }; + int ret; + + ret = spi_sync_transfer(st->spi, xfers, ARRAY_SIZE(xfers)); + if (ret < 0) + return ret; + + *val = sign_extend32(st->scan_data.raw[chan->scan_index], + chan->scan_type.realbits - 1); + + return IIO_VAL_INT; +} + +static int ad7380_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long info) +{ + struct ad7380_state *st = iio_priv(indio_dev); + + switch (info) { + case IIO_CHAN_INFO_RAW: + iio_device_claim_direct_scoped(return -EBUSY, indio_dev) { + return ad7380_read_direct(st, chan, val); + } + unreachable(); + case IIO_CHAN_INFO_SCALE: + /* + * According to the datasheet, the LSB size for fully differential ADC is + * (2 × VREF) / 2^N, where N is the ADC resolution (i.e realbits) + */ + *val = st->vref_mv; + *val2 = chan->scan_type.realbits - 1; + + return IIO_VAL_FRACTIONAL_LOG2; + default: + return -EINVAL; + } +} + +static const struct iio_info ad7380_info = { + .read_raw = &ad7380_read_raw, + .debugfs_reg_access = &ad7380_debugfs_reg_access, +}; + +static int ad7380_init(struct ad7380_state *st, struct regulator *vref) +{ + int ret; + + /* perform hard reset */ + ret = regmap_update_bits(st->regmap, AD7380_REG_ADDR_CONFIG2, + AD7380_CONFIG2_RESET, + FIELD_PREP(AD7380_CONFIG2_RESET, + AD7380_CONFIG2_RESET_HARD)); + if (ret < 0) + return ret; + + /* select internal or external reference voltage */ + ret = regmap_update_bits(st->regmap, AD7380_REG_ADDR_CONFIG1, + AD7380_CONFIG1_REFSEL, + FIELD_PREP(AD7380_CONFIG1_REFSEL, + vref ? 1 : 0)); + if (ret < 0) + return ret; + + /* SPI 1-wire mode */ + return regmap_update_bits(st->regmap, AD7380_REG_ADDR_CONFIG2, + AD7380_CONFIG2_SDO, + FIELD_PREP(AD7380_CONFIG2_SDO, 1)); +} + +static void ad7380_regulator_disable(void *p) +{ + regulator_disable(p); +} + +static int ad7380_probe(struct spi_device *spi) +{ + struct iio_dev *indio_dev; + struct ad7380_state *st; + struct regulator *vref; + int ret; + + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); + if (!indio_dev) + return -ENOMEM; + + st = iio_priv(indio_dev); + st->spi = spi; + st->chip_info = spi_get_device_match_data(spi); + if (!st->chip_info) + return dev_err_probe(&spi->dev, -EINVAL, "missing match data\n"); + + vref = devm_regulator_get_optional(&spi->dev, "refio"); + if (IS_ERR(vref)) { + if (PTR_ERR(vref) != -ENODEV) + return dev_err_probe(&spi->dev, PTR_ERR(vref), + "Failed to get refio regulator\n"); + + vref = NULL; + } + + /* + * If there is no REFIO supply, then it means that we are using + * the internal 2.5V reference, otherwise REFIO is reference voltage. + */ + if (vref) { + ret = regulator_enable(vref); + if (ret) + return ret; + + ret = devm_add_action_or_reset(&spi->dev, + ad7380_regulator_disable, vref); + if (ret) + return ret; + + ret = regulator_get_voltage(vref); + if (ret < 0) + return ret; + + st->vref_mv = ret / 1000; + } else { + st->vref_mv = AD7380_INTERNAL_REF_MV; + } + + st->regmap = devm_regmap_init(&spi->dev, NULL, st, &ad7380_regmap_config); + if (IS_ERR(st->regmap)) + return dev_err_probe(&spi->dev, PTR_ERR(st->regmap), + "failed to allocate register map\n"); + + indio_dev->channels = st->chip_info->channels; + indio_dev->num_channels = st->chip_info->num_channels; + indio_dev->name = st->chip_info->name; + indio_dev->info = &ad7380_info; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->available_scan_masks = ad7380_2_channel_scan_masks; + + ret = devm_iio_triggered_buffer_setup(&spi->dev, indio_dev, + iio_pollfunc_store_time, + ad7380_trigger_handler, NULL); + if (ret) + return ret; + + ret = ad7380_init(st, vref); + if (ret) + return ret; + + return devm_iio_device_register(&spi->dev, indio_dev); +} + +static const struct of_device_id ad7380_of_match_table[] = { + { .compatible = "adi,ad7380", .data = &ad7380_chip_info }, + { .compatible = "adi,ad7381", .data = &ad7381_chip_info }, + { } +}; + +static const struct spi_device_id ad7380_id_table[] = { + { "ad7380", (kernel_ulong_t)&ad7380_chip_info }, + { "ad7381", (kernel_ulong_t)&ad7381_chip_info }, + { } +}; +MODULE_DEVICE_TABLE(spi, ad7380_id_table); + +static struct spi_driver ad7380_driver = { + .driver = { + .name = "ad7380", + .of_match_table = ad7380_of_match_table, + }, + .probe = ad7380_probe, + .id_table = ad7380_id_table, +}; +module_spi_driver(ad7380_driver); + +MODULE_AUTHOR("Stefan Popa "); +MODULE_DESCRIPTION("Analog Devices AD738x ADC driver"); +MODULE_LICENSE("GPL"); From patchwork Wed May 1 14:55:36 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Julien Stephan X-Patchwork-Id: 13650831 Received: from mail-wr1-f41.google.com (mail-wr1-f41.google.com [209.85.221.41]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BB1FA12F58B for ; Wed, 1 May 2024 14:55:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.41 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714575355; cv=none; b=funKlgZ5QQJ6W247CGZedKq3CFNdUS5g1fplMSNYsndZIZanmf6WVEVGA/9oiI5rTOng2atifm+kawqwDiRZTa3EWacHhLwaRJiwSu+Rg8YUXTJTojHDNm5/XkYaXrz88rGAua2hQ9WzpP9Z8H+cxv+84tCwtA9bEbk9t/PpH6c= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714575355; c=relaxed/simple; bh=OB8tgBWPkNRhkYwIg+R2Ji0Wb3SGKEyVa27sOqMTYcs=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Yb2RFVmtHk+oR+z454CMXgtkQ14Bg320gQI/FJKVz5z/oNBSCGKxuUvbvmEjnHN3P5VmRYacd7kvL/j29Nncvm1WyXmd/9ka4HtP7xa0PZemSEKRWbLoK2Jp9zHj/tylzCgQ7xV2VkizAu0aE3EruSjmwtLP8LTYjuVdL8oC8f0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=baylibre.com; spf=pass smtp.mailfrom=baylibre.com; dkim=pass (2048-bit key) header.d=baylibre-com.20230601.gappssmtp.com header.i=@baylibre-com.20230601.gappssmtp.com header.b=Ihh5VOAF; arc=none smtp.client-ip=209.85.221.41 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=baylibre.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=baylibre-com.20230601.gappssmtp.com header.i=@baylibre-com.20230601.gappssmtp.com header.b="Ihh5VOAF" Received: by mail-wr1-f41.google.com with SMTP id ffacd0b85a97d-34dc9065606so384989f8f.1 for ; Wed, 01 May 2024 07:55:53 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1714575352; x=1715180152; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=kJ8CU1KsZdsOI/zOnwTeILM7ZuUE9hyEpMnwtAluPZE=; b=Ihh5VOAF5kqM+khFfNVYVVEgLvdamwx3Rx+OxH6lfnPkr7UyIN8KTqfLhn2LDuHj+X H3NK7Xd1xKAC8uei6tASU3u40u/FOqIVRSm9AFAbhu0Iuqcd8dNeyJXVnuIIYv4IMzgI T6ZXiHbvlAkwr6+f84ODRkH9F30WAucHK09QlEv5E2EqUs+fpSll9/N99RK5gt+8hc+i mQJas8mxfCfCzKzviAbThhJA63v4GbT1vsu1SCae7fc/QpN4FgYe2eq1e9Rqk6GJAt2P gcs7E6PEeXljlbkmrAaLQXzcH4oCnTHQV0h7rKYs1sEDM/S8x8rc+GLvwzfnyY9t1D6z BJeQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1714575352; x=1715180152; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=kJ8CU1KsZdsOI/zOnwTeILM7ZuUE9hyEpMnwtAluPZE=; b=tbAHRSZuN0V5VwL2S3RZfQ3345Q8xo6ecAwG0COjt3uDQH5fBenBmW2x2vp7ZLmXzH +eUxHAZZ9BfhJVg4k8T4dD05rOFIfs70d8FVMl7gyGq6JekqX3cIEMVZKRx2kkv1BFfg RONrrv47EzTApwQnC90+ceKzIAeUjyvhLL5AKA3sjTaL1H5ZabmlKkfJUw8u46mX+xY5 9hYWPmEkHv/rAVjxVQ8SaBejNKwtlijj+cg3osaZy6RfgD4g+45g6srTe+bh6uzmiZzl oWxhGprlX32wK2VGqyA2G++geIpSXNVT7wEaLU8h5MtVJTm4471GEddK5SDf18uU4eCj Z2tw== X-Forwarded-Encrypted: i=1; AJvYcCXqQAP2kyaIW+osbINuSwkuZGT2395xTtho0ox57k9uRt2D84TYW7YC/EXZ95aeZ3oBwA8M5spUR6e2PFC0GZBEFhOc+Ml2yc5G X-Gm-Message-State: AOJu0YxL6izbB6ga3TkwUd7p8CpNgVwMuL9Hltg+RaWrMYqpiYfuZLn9 ec1IpN6pwe1Q2aZ1s+mN2JkybnmkO22X1D5yV3BaIK30OToJfBn30hR+DwRV/vY= X-Google-Smtp-Source: AGHT+IEbjszfmVkTzjjE49mNkp1RDoY6WJdm5Dh/H6CEyFull2eOfXFaa255+mdEhVRdivb1lKxn4A== X-Received: by 2002:adf:e708:0:b0:34d:a37d:d383 with SMTP id c8-20020adfe708000000b0034da37dd383mr3329382wrm.22.1714575352183; Wed, 01 May 2024 07:55:52 -0700 (PDT) Received: from [192.168.1.61] ([2a02:842a:d52e:6101:6fd0:6c4:5d68:f0a5]) by smtp.gmail.com with ESMTPSA id o27-20020a05600c511b00b00418a386c17bsm2422999wms.12.2024.05.01.07.55.51 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 01 May 2024 07:55:52 -0700 (PDT) From: Julien Stephan Date: Wed, 01 May 2024 16:55:36 +0200 Subject: [PATCH RFC v6 03/10] dt-bindings: iio: adc: ad7380: add pseudo-differential parts Precedence: bulk X-Mailing-List: linux-iio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20240501-adding-new-ad738x-driver-v6-3-3c0741154728@baylibre.com> References: <20240501-adding-new-ad738x-driver-v6-0-3c0741154728@baylibre.com> In-Reply-To: <20240501-adding-new-ad738x-driver-v6-0-3c0741154728@baylibre.com> To: Lars-Peter Clausen , Michael Hennerich , =?utf-8?q?Nuno_S=C3=A1?= , David Lechner , Jonathan Cameron , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Liam Girdwood , Mark Brown Cc: kernel test robot , linux-iio@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Julien Stephan , Conor Dooley X-Mailer: b4 0.13.0 From: David Lechner Adding AD7383 and AD7384 compatible parts that are pseudo-differential. Pseudo-differential require common mode voltage supplies, so add them conditionally Signed-off-by: David Lechner Signed-off-by: Julien Stephan Acked-by: Conor Dooley --- .../devicetree/bindings/iio/adc/adi,ad7380.yaml | 32 ++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad7380.yaml b/Documentation/devicetree/bindings/iio/adc/adi,ad7380.yaml index 5e1ee0ebe0a2..de3d28a021ae 100644 --- a/Documentation/devicetree/bindings/iio/adc/adi,ad7380.yaml +++ b/Documentation/devicetree/bindings/iio/adc/adi,ad7380.yaml @@ -13,6 +13,8 @@ maintainers: description: | * https://www.analog.com/en/products/ad7380.html * https://www.analog.com/en/products/ad7381.html + * https://www.analog.com/en/products/ad7383.html + * https://www.analog.com/en/products/ad7384.html $ref: /schemas/spi/spi-peripheral-props.yaml# @@ -21,6 +23,8 @@ properties: enum: - adi,ad7380 - adi,ad7381 + - adi,ad7383 + - adi,ad7384 reg: maxItems: 1 @@ -42,6 +46,16 @@ properties: A 2.5V to 3.3V supply for the external reference voltage. When omitted, the internal 2.5V reference is used. + aina-supply: + description: + The common mode voltage supply for the AINA- pin on pseudo-differential + chips. + + ainb-supply: + description: + The common mode voltage supply for the AINB- pin on pseudo-differential + chips. + interrupts: description: When the device is using 1-wire mode, this property is used to optionally @@ -56,6 +70,24 @@ required: unevaluatedProperties: false +allOf: + # pseudo-differential chips require common mode voltage supplies, + # true differential chips don't use them + - if: + properties: + compatible: + enum: + - adi,ad7383 + - adi,ad7384 + then: + required: + - aina-supply + - ainb-supply + else: + properties: + aina-supply: false + ainb-supply: false + examples: - | #include From patchwork Wed May 1 14:55:37 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Julien Stephan X-Patchwork-Id: 13650833 Received: from mail-wm1-f50.google.com (mail-wm1-f50.google.com [209.85.128.50]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6B14412F59A for ; Wed, 1 May 2024 14:55:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.50 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714575356; cv=none; b=npkN2iwfySdtGCCJayFPKx32C1CQjjM84KWxlU9Y014lxkXyEgcqRNOePMemMrV32T0VwKJ0tZ4tqEVBgt5viXTdQzal290RLr7ATfH4wvB/01fueJy0zmvtuCXs+F9kTV5C4FNsbfdpaevQIFxeTta2G5x/7mO27WOX7hS2oXM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714575356; c=relaxed/simple; bh=pkf8/LBRCf3QFRHG5cHQzVuVo0laS5hX0xG0KSpAu9o=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=akIQTrviaruZeADooOehqaUsyglzYKzbnKl9mGzFGa8epcAnxZ8KRg8e3m7pt1VTAE+ORNXGdN9gjEaTM7mxAga44gcBlzpzLYF56XcrgNoOE+ocMpL1I3GwzvO/qc6QBt52uyWb9ZPHj4a3wKmPCMnn6DpLeEslWToeNXhi5TM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=baylibre.com; spf=pass smtp.mailfrom=baylibre.com; dkim=pass (2048-bit key) header.d=baylibre-com.20230601.gappssmtp.com header.i=@baylibre-com.20230601.gappssmtp.com header.b=nc3mPf9I; arc=none smtp.client-ip=209.85.128.50 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=baylibre.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=baylibre-com.20230601.gappssmtp.com header.i=@baylibre-com.20230601.gappssmtp.com header.b="nc3mPf9I" Received: by mail-wm1-f50.google.com with SMTP id 5b1f17b1804b1-41b794510cdso44214695e9.2 for ; Wed, 01 May 2024 07:55:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1714575353; x=1715180153; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=z2zQ8GQKC8PPzpOVhoeg1QxOlQu6eFpvStLY4dMmkvU=; b=nc3mPf9ItVYKwtVIu3v3fQyya0674yswZqYmKkLoaVQxydT4DakF08WBDLjkfc2dKo yrTr2bOEUAJYKJnaBuDi9QRjax6/2hLcjJV6vJShOS+DTKz2jR8qMprpo76loPyA5v0a Uxl6F7YtIQMhehrqI73ovXndnKG17AmQA2NZ/SAg4dAuHkjqNjjqOCIcK9iSLsO7qYGq wZJd3d9MODW+nkls9x50IHtYwD76WnGat5ysVJqkOWtV9zVP96qJO4LV1Z1C4X7JgnYD D6OL4LhIFTfiixlXFLd28PlVRAfU4/6BXxcPcMIhKk6raJvfZ/rzbJgPlIgYWcMBM6m0 pV+w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1714575353; x=1715180153; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=z2zQ8GQKC8PPzpOVhoeg1QxOlQu6eFpvStLY4dMmkvU=; b=kVqhnBFH8OmKs4y2eR3m8txvxSfmtcRk7sqWGcR44Lj/CYeorkjV1D2DEy6y065yYQ k+BihWpEPQNpIL7AnHHpx102/t8oraiwDHoAixu3HABKtfwugJEvCPq/e+XSxnS0wgVj iX5GxK9RN7nzYCZMktJ1ecX7lJglhb9BrkfG4AMiP5R0L+mPB2dyDylelBlb16sJpnGb 8JHIaMaSB0bO7Z2VZH5wvP9DBT1GJuarSOlUyXVXbJOHovWltCUzzoxVoGo/0BT28KJy dxt8ktyp1L2EdlYOhOV71OfWTmyXwTcgEN11YDzircfPPXgNrcjDUVPgHSRFFV9z/fxX b3kw== X-Forwarded-Encrypted: i=1; AJvYcCVN26cvnNYEZZK3jbLgsCKR+QWAHU8vGINuzI3blYDiyPhCKIpptUswdtqfKPVJkehzeu7nIL15Qf8QBn6eATk9p7/6bNrHW3nB X-Gm-Message-State: AOJu0YzhrtLQfJ+BN590T+tBRBLjSOugr2UBKfWkez/HAnBOL0kOP38d dLuWG03knm1g8dYBbz6wLpvlVQMNOmpom9tfnEes1mNARLJ2QAgCTEBUoOR95lA= X-Google-Smtp-Source: AGHT+IGBz8W9nhzACKGWf4RlR4Hiqj1BQdAdiHE4fm1+pfhBTIRnjURKhxDOzFO2p/pjRMJ/UFm4bA== X-Received: by 2002:a05:600c:4fd3:b0:41c:9155:fbe6 with SMTP id o19-20020a05600c4fd300b0041c9155fbe6mr1791507wmq.17.1714575352879; Wed, 01 May 2024 07:55:52 -0700 (PDT) Received: from [192.168.1.61] ([2a02:842a:d52e:6101:6fd0:6c4:5d68:f0a5]) by smtp.gmail.com with ESMTPSA id o27-20020a05600c511b00b00418a386c17bsm2422999wms.12.2024.05.01.07.55.52 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 01 May 2024 07:55:52 -0700 (PDT) From: Julien Stephan Date: Wed, 01 May 2024 16:55:37 +0200 Subject: [PATCH RFC v6 04/10] iio: adc: ad7380: add support for pseudo-differential parts Precedence: bulk X-Mailing-List: linux-iio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20240501-adding-new-ad738x-driver-v6-4-3c0741154728@baylibre.com> References: <20240501-adding-new-ad738x-driver-v6-0-3c0741154728@baylibre.com> In-Reply-To: <20240501-adding-new-ad738x-driver-v6-0-3c0741154728@baylibre.com> To: Lars-Peter Clausen , Michael Hennerich , =?utf-8?q?Nuno_S=C3=A1?= , David Lechner , Jonathan Cameron , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Liam Girdwood , Mark Brown Cc: kernel test robot , linux-iio@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Julien Stephan X-Mailer: b4 0.13.0 From: David Lechner Add support for AD7383, AD7384 pseudo-differential compatible parts. Pseudo differential parts require common mode voltage supplies so add the support for them and add the support of IIO_CHAN_INFO_OFFSET to retrieve the offset Signed-off-by: David Lechner Signed-off-by: Julien Stephan --- drivers/iio/adc/ad7380.c | 110 ++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 94 insertions(+), 16 deletions(-) diff --git a/drivers/iio/adc/ad7380.c b/drivers/iio/adc/ad7380.c index a218f59c276e..d6abce6d45d3 100644 --- a/drivers/iio/adc/ad7380.c +++ b/drivers/iio/adc/ad7380.c @@ -7,6 +7,7 @@ * * Datasheets of supported parts: * ad7380/1 : https://www.analog.com/media/en/technical-documentation/data-sheets/AD7380-7381.pdf + * ad7383/4 : https://www.analog.com/media/en/technical-documentation/data-sheets/ad7383-7384.pdf */ #include @@ -68,16 +69,19 @@ struct ad7380_chip_info { const char *name; const struct iio_chan_spec *channels; unsigned int num_channels; + const char * const *vcm_supplies; + unsigned int num_vcm_supplies; }; -#define AD7380_CHANNEL(index, bits) { \ +#define AD7380_CHANNEL(index, bits, diff) { \ .type = IIO_VOLTAGE, \ - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ + ((diff) ? 0 : BIT(IIO_CHAN_INFO_OFFSET)), \ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ .indexed = 1, \ - .differential = 1, \ - .channel = 2 * (index), \ - .channel2 = 2 * (index) + 1, \ + .differential = (diff), \ + .channel = (diff) ? (2 * (index)) : (index), \ + .channel2 = (diff) ? (2 * (index) + 1) : 0, \ .scan_index = (index), \ .scan_type = { \ .sign = 's', \ @@ -87,15 +91,23 @@ struct ad7380_chip_info { }, \ } -#define DEFINE_AD7380_2_CHANNEL(name, bits) \ -static const struct iio_chan_spec name[] = { \ - AD7380_CHANNEL(0, bits), \ - AD7380_CHANNEL(1, bits), \ - IIO_CHAN_SOFT_TIMESTAMP(2), \ +#define DEFINE_AD7380_2_CHANNEL(name, bits, diff) \ +static const struct iio_chan_spec name[] = { \ + AD7380_CHANNEL(0, bits, diff), \ + AD7380_CHANNEL(1, bits, diff), \ + IIO_CHAN_SOFT_TIMESTAMP(2), \ } -DEFINE_AD7380_2_CHANNEL(ad7380_channels, 16); -DEFINE_AD7380_2_CHANNEL(ad7381_channels, 14); +/* fully differential */ +DEFINE_AD7380_2_CHANNEL(ad7380_channels, 16, 1); +DEFINE_AD7380_2_CHANNEL(ad7381_channels, 14, 1); +/* pseudo differential */ +DEFINE_AD7380_2_CHANNEL(ad7383_channels, 16, 0); +DEFINE_AD7380_2_CHANNEL(ad7384_channels, 14, 0); + +static const char * const ad7380_2_channel_vcm_supplies[] = { + "aina", "ainb", +}; /* Since this is simultaneous sampling, we don't allow individual channels. */ static const unsigned long ad7380_2_channel_scan_masks[] = { @@ -115,11 +127,28 @@ static const struct ad7380_chip_info ad7381_chip_info = { .num_channels = ARRAY_SIZE(ad7381_channels), }; +static const struct ad7380_chip_info ad7383_chip_info = { + .name = "ad7383", + .channels = ad7383_channels, + .num_channels = ARRAY_SIZE(ad7383_channels), + .vcm_supplies = ad7380_2_channel_vcm_supplies, + .num_vcm_supplies = ARRAY_SIZE(ad7380_2_channel_vcm_supplies), +}; + +static const struct ad7380_chip_info ad7384_chip_info = { + .name = "ad7384", + .channels = ad7384_channels, + .num_channels = ARRAY_SIZE(ad7384_channels), + .vcm_supplies = ad7380_2_channel_vcm_supplies, + .num_vcm_supplies = ARRAY_SIZE(ad7380_2_channel_vcm_supplies), +}; + struct ad7380_state { const struct ad7380_chip_info *chip_info; struct spi_device *spi; struct regmap *regmap; unsigned int vref_mv; + unsigned int vcm_mv[2]; /* * DMA (thus cache coherency maintenance) requires the * transfer buffers to live in their own cache lines. @@ -293,13 +322,24 @@ static int ad7380_read_raw(struct iio_dev *indio_dev, unreachable(); case IIO_CHAN_INFO_SCALE: /* - * According to the datasheet, the LSB size for fully differential ADC is - * (2 × VREF) / 2^N, where N is the ADC resolution (i.e realbits) + * According to the datasheet, the LSB size is: + * * (2 × VREF) / 2^N, for differential chips + * * VREF / 2^N, for pseudo-differential chips + * where N is the ADC resolution (i.e realbits) */ *val = st->vref_mv; - *val2 = chan->scan_type.realbits - 1; + *val2 = chan->scan_type.realbits - chan->differential; return IIO_VAL_FRACTIONAL_LOG2; + case IIO_CHAN_INFO_OFFSET: + /* + * According to IIO ABI, offset is applied before scale, + * so offset is: vcm_mv / scale + */ + *val = st->vcm_mv[chan->channel] * (1 << chan->scan_type.realbits) + / st->vref_mv; + + return IIO_VAL_INT; default: return -EINVAL; } @@ -346,7 +386,7 @@ static int ad7380_probe(struct spi_device *spi) struct iio_dev *indio_dev; struct ad7380_state *st; struct regulator *vref; - int ret; + int ret, i; indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); if (!indio_dev) @@ -390,6 +430,40 @@ static int ad7380_probe(struct spi_device *spi) st->vref_mv = AD7380_INTERNAL_REF_MV; } + if (st->chip_info->num_vcm_supplies > ARRAY_SIZE(st->vcm_mv)) + return dev_err_probe(&spi->dev, -EINVAL, + "invalid number of VCM supplies\n"); + + /* + * pseudo-differential chips have common mode supplies for the negative + * input pin. + */ + for (i = 0; i < st->chip_info->num_vcm_supplies; i++) { + struct regulator *vcm; + + vcm = devm_regulator_get(&spi->dev, + st->chip_info->vcm_supplies[i]); + if (IS_ERR(vcm)) + return dev_err_probe(&spi->dev, PTR_ERR(vcm), + "Failed to get %s regulator\n", + st->chip_info->vcm_supplies[i]); + + ret = regulator_enable(vcm); + if (ret) + return ret; + + ret = devm_add_action_or_reset(&spi->dev, + ad7380_regulator_disable, vcm); + if (ret) + return ret; + + ret = regulator_get_voltage(vcm); + if (ret < 0) + return ret; + + st->vcm_mv[i] = ret / 1000; + } + st->regmap = devm_regmap_init(&spi->dev, NULL, st, &ad7380_regmap_config); if (IS_ERR(st->regmap)) return dev_err_probe(&spi->dev, PTR_ERR(st->regmap), @@ -418,12 +492,16 @@ static int ad7380_probe(struct spi_device *spi) static const struct of_device_id ad7380_of_match_table[] = { { .compatible = "adi,ad7380", .data = &ad7380_chip_info }, { .compatible = "adi,ad7381", .data = &ad7381_chip_info }, + { .compatible = "adi,ad7383", .data = &ad7383_chip_info }, + { .compatible = "adi,ad7384", .data = &ad7384_chip_info }, { } }; static const struct spi_device_id ad7380_id_table[] = { { "ad7380", (kernel_ulong_t)&ad7380_chip_info }, { "ad7381", (kernel_ulong_t)&ad7381_chip_info }, + { "ad7383", (kernel_ulong_t)&ad7383_chip_info }, + { "ad7384", (kernel_ulong_t)&ad7384_chip_info }, { } }; MODULE_DEVICE_TABLE(spi, ad7380_id_table); From patchwork Wed May 1 14:55:38 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Julien Stephan X-Patchwork-Id: 13650834 Received: from mail-lj1-f175.google.com (mail-lj1-f175.google.com [209.85.208.175]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 359BC12FF6E for ; Wed, 1 May 2024 14:55:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.175 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714575359; cv=none; b=Q7PnYJTqaXcMTm7ISrj6Sd/cEXMtZC3BOzHdRaUmyWqlK2mM9WrFYma/Ls8j0sbvlXho9WJ9/BJUe2JPZSgSgfOUkzjv61eUnrnjD73MrwPmNxFs0w6aKGJdsqISg57ZME9rzyBSXcHy1UNdowKGC7D3qpeP/auIpSX2BvFxugk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714575359; c=relaxed/simple; bh=PlVN8xXeJpQxRFCg/Zbc/zFXTyCgg9A5cV1m+rK2HuU=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=QYE6UNbYCqUqYfBs+FCTc5+4N67qG9SaQbrW+t87mMNOx5EmmqRpRbGNdLa1WNPyBR2yhwlzhYLzMoWV8gdZXVUj0UBIXXT+J6EF/TG4TIr1MeLZKPfxBWChB8CJCOPyFfR1bHp+J0W5/OTYXuX9cVvQnhgDYLgbeb8QnNh/5TE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=baylibre.com; spf=pass smtp.mailfrom=baylibre.com; dkim=pass (2048-bit key) header.d=baylibre-com.20230601.gappssmtp.com header.i=@baylibre-com.20230601.gappssmtp.com header.b=3Je228iL; arc=none smtp.client-ip=209.85.208.175 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=baylibre.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=baylibre-com.20230601.gappssmtp.com header.i=@baylibre-com.20230601.gappssmtp.com header.b="3Je228iL" Received: by mail-lj1-f175.google.com with SMTP id 38308e7fff4ca-2df83058d48so57775081fa.1 for ; Wed, 01 May 2024 07:55:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1714575355; x=1715180155; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=jAPd7+I9U5+1I8Z6YQiXd//LKxCaLInr9ip5Pmkk0XE=; b=3Je228iL7Mk2LUzdz6SM9FguE3nmTT0wxhTQCPrYrWycUUeTssu+km+wPpPFnNATkA +Cl3TFOFjD5n7MlCKB7ccQ2+XRb+yLETHGdTr4nhrhHpM3CdQZTo/lxerlY0NjgSaxZ2 Q40bgK++cKLVx1LttwDI1jK2PXPNWZqsaQRFxmS3ol9a82ka4ppBRHq6cO8uG2/cEkMW asMLLrHX4BxnVraBv95VUQ1d0T1A1WrwS02BsRaOcxmRewVZBqfjVUti7E2vvsGYfvyF nNe2+8r8yXb1HRlg6OMGfI9Sad38FUut3/ig1t/RD/Zg5MIUeY8u1c6t//2Ak2uvbUZ4 Hezg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1714575355; x=1715180155; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=jAPd7+I9U5+1I8Z6YQiXd//LKxCaLInr9ip5Pmkk0XE=; b=l/qXCVm6WmyLJM0NuqoRGC6zrm3nWFC/Oo+MGeMwxWUHITkMGdjt7nSrfCkIFo2MrL oKnOLl0lfsJ/AAs//dAxBrJ2UwN69GaXrv8M3pLMHBncKWku2dVlz4h+P+k5Z/pnFMQK isi1HWivxifrI7PSbHPX/pCPulp0F5gvbfj/1oQL4mV3ZjthvTM8wteMlqoCbf+ITQoO EuKe4xxkc3V9Ne+kCZpxDk81rkiLo2owL59H0N+K2pq6Y/G8c9t9rLbMLnbia8eIAPpY FF22mbaDLLC1bazCnu06Vm0LNCPo1wa6VODgdDftwOb3FZk3qACKveMzQLIi4nHAqtzb TpOg== X-Forwarded-Encrypted: i=1; AJvYcCXc0nicRMB7YoV1zrKbNlwrHugTxKwf16llqiJ0W2hpPx7j96e+4fNJpIUdtEeqeKniyT19lpeN+yWqGWLNQN1oVQrAlUms9xtQ X-Gm-Message-State: AOJu0YwU+QLUD9SjzuV5Xv4SVO1RZgu7hV3+NPfJYcx2HpBkbJWH/ofI JdATdym/7kGpHsUUnpDxfnHeVgsSpYeEsK9xkN3aHKEyO1GoTWPYW0DDyyYKDh8= X-Google-Smtp-Source: AGHT+IETnXzT+yQs6Yj2CWqIQQetQPoDaLRkkWGMsrtIM9SAobTswOR6AFvtKqMV9AqyM9AlDvmm6w== X-Received: by 2002:a2e:a7d1:0:b0:2e0:4a32:1f41 with SMTP id x17-20020a2ea7d1000000b002e04a321f41mr2092149ljp.19.1714575353548; Wed, 01 May 2024 07:55:53 -0700 (PDT) Received: from [192.168.1.61] ([2a02:842a:d52e:6101:6fd0:6c4:5d68:f0a5]) by smtp.gmail.com with ESMTPSA id o27-20020a05600c511b00b00418a386c17bsm2422999wms.12.2024.05.01.07.55.53 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 01 May 2024 07:55:53 -0700 (PDT) From: Julien Stephan Date: Wed, 01 May 2024 16:55:38 +0200 Subject: [PATCH RFC v6 05/10] iio: adc: ad7380: prepare for parts with more channels Precedence: bulk X-Mailing-List: linux-iio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20240501-adding-new-ad738x-driver-v6-5-3c0741154728@baylibre.com> References: <20240501-adding-new-ad738x-driver-v6-0-3c0741154728@baylibre.com> In-Reply-To: <20240501-adding-new-ad738x-driver-v6-0-3c0741154728@baylibre.com> To: Lars-Peter Clausen , Michael Hennerich , =?utf-8?q?Nuno_S=C3=A1?= , David Lechner , Jonathan Cameron , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Liam Girdwood , Mark Brown Cc: kernel test robot , linux-iio@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Julien Stephan X-Mailer: b4 0.13.0 The current driver supports only parts with 2 channels. In order to prepare the support of new compatible ADCs with more channels, this commit: - defines MAX_NUM_CHANNEL to specify the maximum number of channels currently supported by the driver - adds available_scan_mask member in ad7380_chip_info structure - fixes spi xfer struct len depending on number of channels - fixes scan_data.raw buffer size to handle more channels - adds a timing specifications structure in ad7380_chip_info structure Signed-off-by: Julien Stephan --- drivers/iio/adc/ad7380.c | 43 +++++++++++++++++++++++++++++++++---------- 1 file changed, 33 insertions(+), 10 deletions(-) diff --git a/drivers/iio/adc/ad7380.c b/drivers/iio/adc/ad7380.c index d6abce6d45d3..201006d878f1 100644 --- a/drivers/iio/adc/ad7380.c +++ b/drivers/iio/adc/ad7380.c @@ -29,6 +29,7 @@ #include #include +#define MAX_NUM_CHANNELS 2 /* 2.5V internal reference voltage */ #define AD7380_INTERNAL_REF_MV 2500 @@ -65,12 +66,19 @@ #define AD7380_ALERT_LOW_TH GENMASK(11, 0) #define AD7380_ALERT_HIGH_TH GENMASK(11, 0) +#define T_CONVERT_NS 190 /* conversion time */ +struct ad7380_timing_specs { + const unsigned int t_csh_ns; /* CS minimum high time */ +}; + struct ad7380_chip_info { const char *name; const struct iio_chan_spec *channels; unsigned int num_channels; const char * const *vcm_supplies; unsigned int num_vcm_supplies; + const unsigned long *available_scan_masks; + const struct ad7380_timing_specs *timing_specs; }; #define AD7380_CHANNEL(index, bits, diff) { \ @@ -115,16 +123,24 @@ static const unsigned long ad7380_2_channel_scan_masks[] = { 0 }; +static const struct ad7380_timing_specs ad7380_timing = { + .t_csh_ns = 10, +}; + static const struct ad7380_chip_info ad7380_chip_info = { .name = "ad7380", .channels = ad7380_channels, .num_channels = ARRAY_SIZE(ad7380_channels), + .available_scan_masks = ad7380_2_channel_scan_masks, + .timing_specs = &ad7380_timing, }; static const struct ad7380_chip_info ad7381_chip_info = { .name = "ad7381", .channels = ad7381_channels, .num_channels = ARRAY_SIZE(ad7381_channels), + .available_scan_masks = ad7380_2_channel_scan_masks, + .timing_specs = &ad7380_timing, }; static const struct ad7380_chip_info ad7383_chip_info = { @@ -133,6 +149,8 @@ static const struct ad7380_chip_info ad7383_chip_info = { .num_channels = ARRAY_SIZE(ad7383_channels), .vcm_supplies = ad7380_2_channel_vcm_supplies, .num_vcm_supplies = ARRAY_SIZE(ad7380_2_channel_vcm_supplies), + .available_scan_masks = ad7380_2_channel_scan_masks, + .timing_specs = &ad7380_timing, }; static const struct ad7380_chip_info ad7384_chip_info = { @@ -141,6 +159,8 @@ static const struct ad7380_chip_info ad7384_chip_info = { .num_channels = ARRAY_SIZE(ad7384_channels), .vcm_supplies = ad7380_2_channel_vcm_supplies, .num_vcm_supplies = ARRAY_SIZE(ad7380_2_channel_vcm_supplies), + .available_scan_masks = ad7380_2_channel_scan_masks, + .timing_specs = &ad7380_timing, }; struct ad7380_state { @@ -148,15 +168,16 @@ struct ad7380_state { struct spi_device *spi; struct regmap *regmap; unsigned int vref_mv; - unsigned int vcm_mv[2]; + unsigned int vcm_mv[MAX_NUM_CHANNELS]; /* * DMA (thus cache coherency maintenance) requires the * transfer buffers to live in their own cache lines. - * Make the buffer large enough for 2 16-bit samples and one 64-bit + * Make the buffer large enough for MAX_NUM_CHANNELS 16-bit samples and one 64-bit * aligned 64 bit timestamp. + * As MAX_NUM_CHANNELS is 2 the layout of the structure is the same for all parts */ struct { - u16 raw[2]; + u16 raw[MAX_NUM_CHANNELS]; s64 ts __aligned(8); } scan_data __aligned(IIO_DMA_MINALIGN); @@ -194,7 +215,7 @@ static int ad7380_regmap_reg_read(void *context, unsigned int reg, .tx_buf = &st->tx, .cs_change = 1, .cs_change_delay = { - .value = 10, /* t[CSH] */ + .value = st->chip_info->timing_specs->t_csh_ns, .unit = SPI_DELAY_UNIT_NSECS, }, }, { @@ -252,7 +273,8 @@ static irqreturn_t ad7380_trigger_handler(int irq, void *p) struct ad7380_state *st = iio_priv(indio_dev); struct spi_transfer xfer = { .bits_per_word = st->chip_info->channels[0].scan_type.realbits, - .len = 4, + .len = (st->chip_info->num_channels - 1) * + BITS_TO_BYTES(st->chip_info->channels->scan_type.storagebits), .rx_buf = st->scan_data.raw, }; int ret; @@ -279,21 +301,22 @@ static int ad7380_read_direct(struct ad7380_state *st, .speed_hz = AD7380_REG_WR_SPEED_HZ, .bits_per_word = chan->scan_type.realbits, .delay = { - .value = 190, /* t[CONVERT] */ + .value = T_CONVERT_NS, .unit = SPI_DELAY_UNIT_NSECS, }, .cs_change = 1, .cs_change_delay = { - .value = 10, /* t[CSH] */ + .value = st->chip_info->timing_specs->t_csh_ns, .unit = SPI_DELAY_UNIT_NSECS, }, }, - /* then read both channels */ + /* then read all channels */ { .speed_hz = AD7380_REG_WR_SPEED_HZ, .bits_per_word = chan->scan_type.realbits, .rx_buf = st->scan_data.raw, - .len = 4, + .len = (st->chip_info->num_channels - 1) * + ((chan->scan_type.storagebits > 16) ? 4 : 2), }, }; int ret; @@ -474,7 +497,7 @@ static int ad7380_probe(struct spi_device *spi) indio_dev->name = st->chip_info->name; indio_dev->info = &ad7380_info; indio_dev->modes = INDIO_DIRECT_MODE; - indio_dev->available_scan_masks = ad7380_2_channel_scan_masks; + indio_dev->available_scan_masks = st->chip_info->available_scan_masks; ret = devm_iio_triggered_buffer_setup(&spi->dev, indio_dev, iio_pollfunc_store_time, From patchwork Wed May 1 14:55:39 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Julien Stephan X-Patchwork-Id: 13650835 Received: from mail-wm1-f44.google.com (mail-wm1-f44.google.com [209.85.128.44]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 647DC12FF9D for ; Wed, 1 May 2024 14:55:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.44 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714575360; cv=none; b=lRdQkxOsYXmhlERbr9/WZZ+9d9dicbaFQK2GQSs1RlV6aaFsdhLk0UiwL0dCgCYG2yNJRizvyDiGWpJFiKBDA0nviDT6wxAeXQuk2scotKBNFWRLN0cQdsTz74Ip7Vj/CRwTDN7OEiBWK7QtFnJmbtWo5s0x3OKVZw8C9K/7Lr4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714575360; c=relaxed/simple; bh=VQ4RPFjraeg9QG+WtxUK0LxObNrAlrRgeIFZywlwUq0=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=bQ/nUSuSsxs8NT6NaEjxl1oQcc2xL1sAZ+xpTg9oZddtI+Rv+Dfin/ASh++uSStnOO0IoSXI4xZVa1kTM1rXeAdAA7jQZYO1HyKARKaFPNJiDG/GBhhN/xcr/JPhYilyXzzunhLiWsK5Ye0N168IPyMlF3ZGUAGyvIV2Ay97DOM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=baylibre.com; spf=pass smtp.mailfrom=baylibre.com; dkim=pass (2048-bit key) header.d=baylibre-com.20230601.gappssmtp.com header.i=@baylibre-com.20230601.gappssmtp.com header.b=Z5a/zJlt; arc=none smtp.client-ip=209.85.128.44 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=baylibre.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=baylibre-com.20230601.gappssmtp.com header.i=@baylibre-com.20230601.gappssmtp.com header.b="Z5a/zJlt" Received: by mail-wm1-f44.google.com with SMTP id 5b1f17b1804b1-41a1d2a7b81so4729245e9.0 for ; Wed, 01 May 2024 07:55:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1714575357; x=1715180157; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=7kVmMiAww/1MNzSxxAk2mzn+IJ9yIpCfeirFaQBWWao=; b=Z5a/zJltr1B/SgV2vz/KZYVsn526i3YYhIjB6xlRCKu2SdmzFSGSwuuCRv0Hb1aPO4 kX7xjjCnzrtmezVJ7Dg8vkSV0Aqo9lbTpIGMVitVJq0DnKJjV3YB6s3oKp7ZSJPlVyvJ MxSJsuXYdWjSFmhof7eD///F6dR0CKPwH1n/74O1oQey0w9zAOuLwF8xHdNKuWxqF9eA 2eqMRRCqGYBuwwwO7r9J4bjPZEs5rI4mDKgtNMQA9Wu0nZ/Jz+bIUHOdCourH6A/udKo oLj6NQhC9kZySaDsz7UFeXpzX1+SN4z+pXt+DqJskGT4x62dCMWrnwPHIc3Ni05DyU3k Htzw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1714575357; x=1715180157; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=7kVmMiAww/1MNzSxxAk2mzn+IJ9yIpCfeirFaQBWWao=; b=liFPeoNaorUmTFJn5Fl26T55jp4ykUPehj7gGodjYjfhunUEFgj15FcahiomE5K9mg MJ2GXFk/IqcP/CMYTVcLCWFyLw6YCrUMN/+XcqU94PtxQoekKVAELR/nALyhkJraqTQJ 7Us8zluXBRBi4rTUtj1BkXngOWxo6boMBcOyV55S8Brq+fjkuek2cBd/8HfB+45MY+AO bwfT3QB3lFfmLCdCZSE2TtW93hmv92SYjkX4Ua+lT11TN7KIyYALFRNoZ7yQQZyf3qOy QeSHqveYzobP2aUKLhYy7G3i7bh4JYF3qvzQHpmOgW4Oim0gTGHxLc842boShhVrY93w JNTw== X-Forwarded-Encrypted: i=1; AJvYcCU0iD+rCGFpeapB63yJPhUSsg5AxK7kN46im1lSnEgZbP1iIUP08q/P2ep5fEZgi94YWGlRvkhNs1af/WVI5MKBk7whbAQKbEu1 X-Gm-Message-State: AOJu0YwO/P2vdCddMQZepQyxoJ+SeyCPQrzge6NiaBo0/jkuAP10Kf6i 9jqBs43Zn14ZQnNk9HkBAru12Q/KpgOrE6xTjwFRZArkSuccII8wPeIQrsIA3cQ= X-Google-Smtp-Source: AGHT+IEANloY5ykx9Y8v3SvYudon/zDa72AUor3FRJRdAs2hAmb12iii9rrqR7zhQBrbVBg7l3dLXg== X-Received: by 2002:a05:600c:3b10:b0:419:c9e1:70b8 with SMTP id m16-20020a05600c3b1000b00419c9e170b8mr2540608wms.13.1714575356686; Wed, 01 May 2024 07:55:56 -0700 (PDT) Received: from [192.168.1.61] ([2a02:842a:d52e:6101:6fd0:6c4:5d68:f0a5]) by smtp.gmail.com with ESMTPSA id o27-20020a05600c511b00b00418a386c17bsm2422999wms.12.2024.05.01.07.55.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 01 May 2024 07:55:55 -0700 (PDT) From: Julien Stephan Date: Wed, 01 May 2024 16:55:39 +0200 Subject: [PATCH RFC v6 06/10] dt-bindings: iio: adc: ad7380: add support for ad738x-4 4 channels variants Precedence: bulk X-Mailing-List: linux-iio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20240501-adding-new-ad738x-driver-v6-6-3c0741154728@baylibre.com> References: <20240501-adding-new-ad738x-driver-v6-0-3c0741154728@baylibre.com> In-Reply-To: <20240501-adding-new-ad738x-driver-v6-0-3c0741154728@baylibre.com> To: Lars-Peter Clausen , Michael Hennerich , =?utf-8?q?Nuno_S=C3=A1?= , David Lechner , Jonathan Cameron , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Liam Girdwood , Mark Brown Cc: kernel test robot , linux-iio@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Julien Stephan , Conor Dooley X-Mailer: b4 0.13.0 Add compatible support for ad7380/1/3/4-4 parts which are 4 channels variants from ad7380/1/3/4 Signed-off-by: Julien Stephan Acked-by: Conor Dooley --- .../devicetree/bindings/iio/adc/adi,ad7380.yaml | 34 ++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad7380.yaml b/Documentation/devicetree/bindings/iio/adc/adi,ad7380.yaml index de3d28a021ae..899b777017ce 100644 --- a/Documentation/devicetree/bindings/iio/adc/adi,ad7380.yaml +++ b/Documentation/devicetree/bindings/iio/adc/adi,ad7380.yaml @@ -15,6 +15,10 @@ description: | * https://www.analog.com/en/products/ad7381.html * https://www.analog.com/en/products/ad7383.html * https://www.analog.com/en/products/ad7384.html + * https://www.analog.com/en/products/ad7380-4.html + * https://www.analog.com/en/products/ad7381-4.html + * https://www.analog.com/en/products/ad7383-4.html + * https://www.analog.com/en/products/ad7384-4.html $ref: /schemas/spi/spi-peripheral-props.yaml# @@ -25,6 +29,10 @@ properties: - adi,ad7381 - adi,ad7383 - adi,ad7384 + - adi,ad7380-4 + - adi,ad7381-4 + - adi,ad7383-4 + - adi,ad7384-4 reg: maxItems: 1 @@ -56,6 +64,16 @@ properties: The common mode voltage supply for the AINB- pin on pseudo-differential chips. + ainc-supply: + description: + The common mode voltage supply for the AINC- pin on pseudo-differential + chips. + + aind-supply: + description: + The common mode voltage supply for the AIND- pin on pseudo-differential + chips. + interrupts: description: When the device is using 1-wire mode, this property is used to optionally @@ -79,6 +97,8 @@ allOf: enum: - adi,ad7383 - adi,ad7384 + - adi,ad7383-4 + - adi,ad7384-4 then: required: - aina-supply @@ -87,6 +107,20 @@ allOf: properties: aina-supply: false ainb-supply: false + - if: + properties: + compatible: + enum: + - adi,ad7383-4 + - adi,ad7384-4 + then: + required: + - ainc-supply + - aind-supply + else: + properties: + ainc-supply: false + aind-supply: false examples: - | From patchwork Wed May 1 14:55:40 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Julien Stephan X-Patchwork-Id: 13650836 Received: from mail-lj1-f169.google.com (mail-lj1-f169.google.com [209.85.208.169]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1AC2A130492 for ; Wed, 1 May 2024 14:55:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.169 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714575361; cv=none; b=BIm1nv0d3QndC6taxO6kMwlosG1vl5S+u3ezNna0ukZ78bRrUQ0D/go2El+oUfRMpws+seO9Swm81w4LGpOlZC9GD9KDNkGLik/I3scLDJVwKresusUN5ZsqufAideKM7RSaWXEOMf1EXhcIfSDQO9HpYKlYf9oLupDtOYnjKzw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714575361; c=relaxed/simple; bh=ZNQE99beBwoRSVRXgPiuYKEUKZPVmY+MpjIBueQJo5Q=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=L43eFkRvTZqs5HKHOlZIpa1I6QL7WpVrYC/YRljXS8yifU1I5hw6zkbh8aPKoRox4mTv5JzmqG0UcookzXY3yqRcj2wYAsm19HE7v+8BACcg9w8952k3s9wgthTgqlu9PzcUDMeB8UjTp6K5MOyiigwRDZHbY4rhpeIe1KO7dSk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=baylibre.com; spf=pass smtp.mailfrom=baylibre.com; dkim=pass (2048-bit key) header.d=baylibre-com.20230601.gappssmtp.com header.i=@baylibre-com.20230601.gappssmtp.com header.b=VxX37z4q; arc=none smtp.client-ip=209.85.208.169 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=baylibre.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=baylibre-com.20230601.gappssmtp.com header.i=@baylibre-com.20230601.gappssmtp.com header.b="VxX37z4q" Received: by mail-lj1-f169.google.com with SMTP id 38308e7fff4ca-2dcc8d10d39so79953891fa.3 for ; Wed, 01 May 2024 07:55:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1714575357; x=1715180157; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=2SUrAQZGAtrStLGSV72n9ZrFrH3z0Vq+Ea2QpVZsYzA=; b=VxX37z4qwmlW0BReVaadVBfJJ0+OGctDYzNwUb/v5Yjo8yHQxYwE7VQFDbfFyHFrGL FlfxGZVYibs6P5pVpOm09fh2nTC7uAZwzdodfGec4CR97iAQHgPCB/gW9N0IRileSOSS WfpeVX6KhIlpdk8YHROcOmR9/JlKpRKz5uKTK2QsvBCh0F0gwXGHxZoAarksXj1HpP7q 9I+Igh2zEQR1+0HmLDOhNA3oDukZRX7UR8kjkmtJ0G8BI1bm5TlWOPrq2Rq0R5X5dPnN px9ZC3lmD2+ik3kqgonjoDH0MJS4BKqpyRjAum5LHENxwGPMjOblqJGWQ2vdDW1pS8jb 96zw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1714575357; x=1715180157; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=2SUrAQZGAtrStLGSV72n9ZrFrH3z0Vq+Ea2QpVZsYzA=; b=vDseRGZZc2TO2CkW2YSYxhU/MDiXOfjIk9gZD4YdvOOC+YsGiZAfFNcwPxkh98bQXE Pcfsr0VICkDrXTkdi1gOISsUmAc7YqPGERGRuIB3+rqrInv+ebFLFqNpRA+fGEJxkYMl vjCynm5izHtouy5RzvaZNGXjkf/NvDLTkOXB2UUko0rJjSG3CHCfZuojmmLhjwgcXso2 CDtZmYuu/kU5b5WvCd86BtHOwxTePdfktNpBCXrRHpObTXHcNKeAjBA5iW4vCfq0TtvD gAkwHj+si8RNNLndRWUF3CSjfZpzWtveeivhsY5WlDp0GxG+Xq+g18wS8n41cWniUdjU Z0Jg== X-Forwarded-Encrypted: i=1; AJvYcCVljXycB5FcafVK3OO7nUQDGpFVm9RMRyq+YI7Iveg3ktD9XVoU48EDzjf8flX3++CQYwtzVZ5wTL8PyOmYbWrgOjO5UoVmj8px X-Gm-Message-State: AOJu0Ywu1Vt8GxoL6plkvN0lHYBAWb10yKLmVori2SyybmCYdaZDiF3O xo7eYhrN3F+m37T+Vdo2mQO33Uu1j45a+UbrD4fFiO5u2yg5WXkbKfTlI9EW7MU= X-Google-Smtp-Source: AGHT+IEv9sPD9F1hPTXXzQtVy0YeCQSCcJgq28A1F/hSj8DUSPiVAnVdblnxCwk7HLdQcWPj9V/HWQ== X-Received: by 2002:a05:651c:2110:b0:2e1:b0e3:21f with SMTP id a16-20020a05651c211000b002e1b0e3021fmr183264ljq.40.1714575357402; Wed, 01 May 2024 07:55:57 -0700 (PDT) Received: from [192.168.1.61] ([2a02:842a:d52e:6101:6fd0:6c4:5d68:f0a5]) by smtp.gmail.com with ESMTPSA id o27-20020a05600c511b00b00418a386c17bsm2422999wms.12.2024.05.01.07.55.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 01 May 2024 07:55:57 -0700 (PDT) From: Julien Stephan Date: Wed, 01 May 2024 16:55:40 +0200 Subject: [PATCH RFC v6 07/10] iio: adc: ad7380: add support for ad738x-4 4 channels variants Precedence: bulk X-Mailing-List: linux-iio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20240501-adding-new-ad738x-driver-v6-7-3c0741154728@baylibre.com> References: <20240501-adding-new-ad738x-driver-v6-0-3c0741154728@baylibre.com> In-Reply-To: <20240501-adding-new-ad738x-driver-v6-0-3c0741154728@baylibre.com> To: Lars-Peter Clausen , Michael Hennerich , =?utf-8?q?Nuno_S=C3=A1?= , David Lechner , Jonathan Cameron , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Liam Girdwood , Mark Brown Cc: kernel test robot , linux-iio@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Julien Stephan X-Mailer: b4 0.13.0 Add support for ad7380/1/2/3-4 parts which are 4 channels variants from ad7380/1/2/3 Signed-off-by: Julien Stephan --- drivers/iio/adc/ad7380.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 75 insertions(+), 2 deletions(-) diff --git a/drivers/iio/adc/ad7380.c b/drivers/iio/adc/ad7380.c index 201006d878f1..020959759170 100644 --- a/drivers/iio/adc/ad7380.c +++ b/drivers/iio/adc/ad7380.c @@ -8,6 +8,9 @@ * Datasheets of supported parts: * ad7380/1 : https://www.analog.com/media/en/technical-documentation/data-sheets/AD7380-7381.pdf * ad7383/4 : https://www.analog.com/media/en/technical-documentation/data-sheets/ad7383-7384.pdf + * ad7380-4 : https://www.analog.com/media/en/technical-documentation/data-sheets/ad7380-4.pdf + * ad7381-4 : https://www.analog.com/media/en/technical-documentation/data-sheets/ad7381-4.pdf + * ad7383/4-4 : https://www.analog.com/media/en/technical-documentation/data-sheets/ad7383-4-ad7384-4.pdf */ #include @@ -29,7 +32,7 @@ #include #include -#define MAX_NUM_CHANNELS 2 +#define MAX_NUM_CHANNELS 4 /* 2.5V internal reference voltage */ #define AD7380_INTERNAL_REF_MV 2500 @@ -106,27 +109,53 @@ static const struct iio_chan_spec name[] = { \ IIO_CHAN_SOFT_TIMESTAMP(2), \ } +#define DEFINE_AD7380_4_CHANNEL(name, bits, diff) \ +static const struct iio_chan_spec name[] = { \ + AD7380_CHANNEL(0, bits, diff), \ + AD7380_CHANNEL(1, bits, diff), \ + AD7380_CHANNEL(2, bits, diff), \ + AD7380_CHANNEL(3, bits, diff), \ + IIO_CHAN_SOFT_TIMESTAMP(4), \ +} + /* fully differential */ DEFINE_AD7380_2_CHANNEL(ad7380_channels, 16, 1); DEFINE_AD7380_2_CHANNEL(ad7381_channels, 14, 1); +DEFINE_AD7380_4_CHANNEL(ad7380_4_channels, 16, 1); +DEFINE_AD7380_4_CHANNEL(ad7381_4_channels, 14, 1); /* pseudo differential */ DEFINE_AD7380_2_CHANNEL(ad7383_channels, 16, 0); DEFINE_AD7380_2_CHANNEL(ad7384_channels, 14, 0); +DEFINE_AD7380_4_CHANNEL(ad7383_4_channels, 16, 0); +DEFINE_AD7380_4_CHANNEL(ad7384_4_channels, 14, 0); static const char * const ad7380_2_channel_vcm_supplies[] = { "aina", "ainb", }; +static const char * const ad7380_4_channel_vcm_supplies[] = { + "aina", "ainb", "ainc", "aind", +}; + /* Since this is simultaneous sampling, we don't allow individual channels. */ static const unsigned long ad7380_2_channel_scan_masks[] = { GENMASK(1, 0), 0 }; +static const unsigned long ad7380_4_channel_scan_masks[] = { + GENMASK(3, 0), + 0 +}; + static const struct ad7380_timing_specs ad7380_timing = { .t_csh_ns = 10, }; +static const struct ad7380_timing_specs ad7380_4_timing = { + .t_csh_ns = 20, +}; + static const struct ad7380_chip_info ad7380_chip_info = { .name = "ad7380", .channels = ad7380_channels, @@ -163,6 +192,42 @@ static const struct ad7380_chip_info ad7384_chip_info = { .timing_specs = &ad7380_timing, }; +static const struct ad7380_chip_info ad7380_4_chip_info = { + .name = "ad7380-4", + .channels = ad7380_4_channels, + .num_channels = ARRAY_SIZE(ad7380_4_channels), + .available_scan_masks = ad7380_4_channel_scan_masks, + .timing_specs = &ad7380_4_timing, +}; + +static const struct ad7380_chip_info ad7381_4_chip_info = { + .name = "ad7381-4", + .channels = ad7381_4_channels, + .num_channels = ARRAY_SIZE(ad7381_4_channels), + .available_scan_masks = ad7380_4_channel_scan_masks, + .timing_specs = &ad7380_4_timing, +}; + +static const struct ad7380_chip_info ad7383_4_chip_info = { + .name = "ad7383-4", + .channels = ad7383_4_channels, + .num_channels = ARRAY_SIZE(ad7383_4_channels), + .vcm_supplies = ad7380_4_channel_vcm_supplies, + .num_vcm_supplies = ARRAY_SIZE(ad7380_4_channel_vcm_supplies), + .available_scan_masks = ad7380_4_channel_scan_masks, + .timing_specs = &ad7380_4_timing, +}; + +static const struct ad7380_chip_info ad7384_4_chip_info = { + .name = "ad7384-4", + .channels = ad7384_4_channels, + .num_channels = ARRAY_SIZE(ad7384_4_channels), + .vcm_supplies = ad7380_4_channel_vcm_supplies, + .num_vcm_supplies = ARRAY_SIZE(ad7380_4_channel_vcm_supplies), + .available_scan_masks = ad7380_4_channel_scan_masks, + .timing_specs = &ad7380_4_timing, +}; + struct ad7380_state { const struct ad7380_chip_info *chip_info; struct spi_device *spi; @@ -174,7 +239,7 @@ struct ad7380_state { * transfer buffers to live in their own cache lines. * Make the buffer large enough for MAX_NUM_CHANNELS 16-bit samples and one 64-bit * aligned 64 bit timestamp. - * As MAX_NUM_CHANNELS is 2 the layout of the structure is the same for all parts + * As MAX_NUM_CHANNELS is 4 the layout of the structure is the same for all parts */ struct { u16 raw[MAX_NUM_CHANNELS]; @@ -517,6 +582,10 @@ static const struct of_device_id ad7380_of_match_table[] = { { .compatible = "adi,ad7381", .data = &ad7381_chip_info }, { .compatible = "adi,ad7383", .data = &ad7383_chip_info }, { .compatible = "adi,ad7384", .data = &ad7384_chip_info }, + { .compatible = "adi,ad7380-4", .data = &ad7380_4_chip_info }, + { .compatible = "adi,ad7381-4", .data = &ad7381_4_chip_info }, + { .compatible = "adi,ad7383-4", .data = &ad7383_4_chip_info }, + { .compatible = "adi,ad7384-4", .data = &ad7384_4_chip_info }, { } }; @@ -525,6 +594,10 @@ static const struct spi_device_id ad7380_id_table[] = { { "ad7381", (kernel_ulong_t)&ad7381_chip_info }, { "ad7383", (kernel_ulong_t)&ad7383_chip_info }, { "ad7384", (kernel_ulong_t)&ad7384_chip_info }, + { "ad7380-4", (kernel_ulong_t)&ad7380_4_chip_info }, + { "ad7381-4", (kernel_ulong_t)&ad7381_4_chip_info }, + { "ad7383-4", (kernel_ulong_t)&ad7383_4_chip_info }, + { "ad7384-4", (kernel_ulong_t)&ad7384_4_chip_info }, { } }; MODULE_DEVICE_TABLE(spi, ad7380_id_table); From patchwork Wed May 1 14:55:41 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Julien Stephan X-Patchwork-Id: 13650837 Received: from mail-wm1-f53.google.com (mail-wm1-f53.google.com [209.85.128.53]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CC0B41304A1 for ; Wed, 1 May 2024 14:55:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.53 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714575361; cv=none; b=OSH/mYuxJhoOunkA6v6hLNm8KelSQXp6zsEEWWQT/XdnRNoMvBxLtPGY3GnkZLRVoy1cWLD/YDnaZrGKNgXnN55Xyt+czpShDBliw+d0hSgC8NygUiYkxYQhVsFaTgwo8ckGaigma1QYP9lPEnsC8mMtNsQe5RuMWZcGmPbQbMs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714575361; c=relaxed/simple; bh=qpYpssS45nruTsiAVK4hIr/DfAzCuG8bb/CkuI//dIU=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=hDawL4NQI5I5ItGH1XW0NwoOFO6Q0Jyqp6aW/Y8h69uzm7Nvv7yQYcAQMwtgtCVsC7kgOFwWSfh4PSkmeaBwV+58Gs+8hMv4AsnyStcgP/W6L2tRbvsosLnG/WTmo6i6NGsagZS/OXZVpgg62jNML5/fW96QbGa1nOYxU3M5gLg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=baylibre.com; spf=pass smtp.mailfrom=baylibre.com; dkim=pass (2048-bit key) header.d=baylibre-com.20230601.gappssmtp.com header.i=@baylibre-com.20230601.gappssmtp.com header.b=PH+W5njQ; arc=none smtp.client-ip=209.85.128.53 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=baylibre.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=baylibre-com.20230601.gappssmtp.com header.i=@baylibre-com.20230601.gappssmtp.com header.b="PH+W5njQ" Received: by mail-wm1-f53.google.com with SMTP id 5b1f17b1804b1-41b79450f8cso43698925e9.3 for ; Wed, 01 May 2024 07:55:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1714575358; x=1715180158; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=IikJd/LplXd0GAQdyekbojR8JRFhxUeGGR+Ui18yUXw=; b=PH+W5njQ+qduIHHTNik2dCCqKLDxCkqQYhfvagpK+2baB2vmBR85h3ZjuAg1N4cawV 83h+y3Y/48x1ShyzWC4qin/25cBked63oKulrHDmcLu/Qy/eADlZCiB+n6qnlCDIb+Zn I5TIdjIBv4tTKc5YdiF3ToVS8QToHz/4YZh5deJ2iBzWOuvuXxsCsHzh34cQDjqa0ptZ s25FIxXkBnMx2wFn111MMIRxBOfRvvmEdZEAyXVa0uY5LDx9ycq5NWLEmxz8uvfh1kcx M34bRrCejopZdNb2wVLCwPYJ/7UZvYj09Q2vbyccLdQRQybnTUa2bdVTdZowfv1Oad8y KGUA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1714575358; x=1715180158; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=IikJd/LplXd0GAQdyekbojR8JRFhxUeGGR+Ui18yUXw=; b=cfnVXfnXNyWxw6Ji8e5eWBxj1/oBuij4rHnskKCcASdOTvGuexMUxAhD91BMRW6H6u +4S+6hHG52FleLmd817zJZ67314f//KM3wUtPRsuoUQecP7lQbrwKw1ETxuiwbCGDIQo KRpWZEfX9SjD1HS24sgLjbHaxK53YfFbzZsT4DPrISEBei3I6U2hsk6W+8kkL4vO6GOw +QuIOXBQy58UwRQj/wlJpv62OFC0jJc3prhA6Xp5qszfvNc+Zjjn2G2lP9mvW0GQACA7 CMu3LPQWse5GqTjJmRnsmN3XjGw3FNm/UWJGI4cj/AMsav24lATRhnNZEEcmbcnIYqKW 2DWQ== X-Forwarded-Encrypted: i=1; AJvYcCWewlG0yJXsjoBGii+9PU/PP2l1H4gU/dlG14wqoAuopyLcQTpbBG3jnR+fJBfTYCJZZDbDZnCjCRYYlIA7UHSuH+oYPo2r8m0F X-Gm-Message-State: AOJu0Yx7GTJm+RIiPYA1EHGmYPQ/+UN870/25wsboVp+sJZqjT9t4zmz o8Y4nqNx5ODODN/8hYUCOVN476um+hdpofTJ+taH02UDkX9jZuuQP94egEk/57E= X-Google-Smtp-Source: AGHT+IF4RI3DWH3O6s2iqU3cnNMEynbpVDI4WzhAtH0r6Hgxn6Ww74V8vUuYJ4goPrb2+hzQO9Uhhw== X-Received: by 2002:a05:600c:4751:b0:41b:4443:9e10 with SMTP id w17-20020a05600c475100b0041b44439e10mr1954285wmo.29.1714575358123; Wed, 01 May 2024 07:55:58 -0700 (PDT) Received: from [192.168.1.61] ([2a02:842a:d52e:6101:6fd0:6c4:5d68:f0a5]) by smtp.gmail.com with ESMTPSA id o27-20020a05600c511b00b00418a386c17bsm2422999wms.12.2024.05.01.07.55.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 01 May 2024 07:55:57 -0700 (PDT) From: Julien Stephan Date: Wed, 01 May 2024 16:55:41 +0200 Subject: [PATCH RFC v6 08/10] iio: adc: ad7380: add oversampling support Precedence: bulk X-Mailing-List: linux-iio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20240501-adding-new-ad738x-driver-v6-8-3c0741154728@baylibre.com> References: <20240501-adding-new-ad738x-driver-v6-0-3c0741154728@baylibre.com> In-Reply-To: <20240501-adding-new-ad738x-driver-v6-0-3c0741154728@baylibre.com> To: Lars-Peter Clausen , Michael Hennerich , =?utf-8?q?Nuno_S=C3=A1?= , David Lechner , Jonathan Cameron , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Liam Girdwood , Mark Brown Cc: kernel test robot , linux-iio@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Julien Stephan X-Mailer: b4 0.13.0 ad7380x(-4) parts are able to do oversampling to increase accuracy. They support 2 average modes: normal average and rolling overage. This commits focus on enabling normal average oversampling, which is the default one. Normal averaging involves taking a number of samples, adding them together, and dividing the result by the number of samples taken. This result is then output from the device. The sample data is cleared when the process completes. Because we need more samples to output a value, the data output rate decrease with the oversampling ratio. Signed-off-by: Julien Stephan --- drivers/iio/adc/ad7380.c | 115 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 114 insertions(+), 1 deletion(-) diff --git a/drivers/iio/adc/ad7380.c b/drivers/iio/adc/ad7380.c index 020959759170..1e3869f5e48c 100644 --- a/drivers/iio/adc/ad7380.c +++ b/drivers/iio/adc/ad7380.c @@ -88,7 +88,10 @@ struct ad7380_chip_info { .type = IIO_VOLTAGE, \ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ ((diff) ? 0 : BIT(IIO_CHAN_INFO_OFFSET)), \ - .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \ + .info_mask_shared_by_type_available = \ + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \ .indexed = 1, \ .differential = (diff), \ .channel = (diff) ? (2 * (index)) : (index), \ @@ -156,6 +159,16 @@ static const struct ad7380_timing_specs ad7380_4_timing = { .t_csh_ns = 20, }; +/* + * Available oversampling ratios. The indices correspond + * with the bit value expected by the chip. + * The available ratios depend on the averaging mode, + * only normal averaging is supported for now + */ +static const int ad7380_normal_average_oversampling_ratios[] = { + 1, 2, 4, 8, 16, 32, +}; + static const struct ad7380_chip_info ad7380_chip_info = { .name = "ad7380", .channels = ad7380_channels, @@ -231,6 +244,7 @@ static const struct ad7380_chip_info ad7384_4_chip_info = { struct ad7380_state { const struct ad7380_chip_info *chip_info; struct spi_device *spi; + unsigned int oversampling_ratio; struct regmap *regmap; unsigned int vref_mv; unsigned int vcm_mv[MAX_NUM_CHANNELS]; @@ -386,6 +400,12 @@ static int ad7380_read_direct(struct ad7380_state *st, }; int ret; + /* + * In normal average oversampling we need to wait for multiple conversions to be done + */ + if (st->oversampling_ratio > 1) + xfers[0].delay.value = T_CONVERT_NS + 500 * st->oversampling_ratio; + ret = spi_sync_transfer(st->spi, xfers, ARRAY_SIZE(xfers)); if (ret < 0) return ret; @@ -428,6 +448,91 @@ static int ad7380_read_raw(struct iio_dev *indio_dev, / st->vref_mv; return IIO_VAL_INT; + case IIO_CHAN_INFO_OVERSAMPLING_RATIO: + *val = st->oversampling_ratio; + + return IIO_VAL_INT; + default: + return -EINVAL; + } +} + +static int ad7380_read_avail(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + const int **vals, int *type, int *length, + long mask) +{ + switch (mask) { + case IIO_CHAN_INFO_OVERSAMPLING_RATIO: + *vals = ad7380_normal_average_oversampling_ratios; + *length = ARRAY_SIZE(ad7380_normal_average_oversampling_ratios); + *type = IIO_VAL_INT; + + return IIO_AVAIL_LIST; + default: + return -EINVAL; + } +} + +/** + * check_osr - Check the oversampling ratio + * @available_ratio: available ratios's array + * @size: size of the available_ratio array + * ratio: ratio to check + * + * Check if ratio is present in @available_ratio. Check for exact match. + * @available_ratio is an array of the available ratios (depending on the oversampling mode). + * The indices must correspond with the bit value expected by the chip. + */ +static inline int check_osr(const int *available_ratio, int size, int ratio) +{ + int i; + + for (i = 0; i < size; i++) { + if (ratio == available_ratio[i]) + return i; + } + + return -EINVAL; +} + +static int ad7380_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int val, + int val2, long mask) +{ + struct ad7380_state *st = iio_priv(indio_dev); + int ret, osr; + + switch (mask) { + case IIO_CHAN_INFO_OVERSAMPLING_RATIO: + osr = check_osr(ad7380_normal_average_oversampling_ratios, + ARRAY_SIZE(ad7380_normal_average_oversampling_ratios), + val); + + if (osr < 0) + return osr; + + iio_device_claim_direct_scoped(return -EBUSY, indio_dev) { + ret = regmap_update_bits(st->regmap, AD7380_REG_ADDR_CONFIG1, + AD7380_CONFIG1_OSR, + FIELD_PREP(AD7380_CONFIG1_OSR, osr)); + + if (ret) + return ret; + + st->oversampling_ratio = val; + + /* + * Perform a soft reset. + * This will flush the oversampling block and FIFO but will + * maintain the content of the configurable registers. + */ + ret = regmap_update_bits(st->regmap, AD7380_REG_ADDR_CONFIG2, + AD7380_CONFIG2_RESET, + FIELD_PREP(AD7380_CONFIG2_RESET, + AD7380_CONFIG2_RESET_SOFT)); + } + return 0; default: return -EINVAL; } @@ -435,6 +540,8 @@ static int ad7380_read_raw(struct iio_dev *indio_dev, static const struct iio_info ad7380_info = { .read_raw = &ad7380_read_raw, + .read_avail = &ad7380_read_avail, + .write_raw = &ad7380_write_raw, .debugfs_reg_access = &ad7380_debugfs_reg_access, }; @@ -458,6 +565,12 @@ static int ad7380_init(struct ad7380_state *st, struct regulator *vref) if (ret < 0) return ret; + /* Disable oversampling by default. + * This is the default value after reset, + * so just initialize internal data + */ + st->oversampling_ratio = 1; + /* SPI 1-wire mode */ return regmap_update_bits(st->regmap, AD7380_REG_ADDR_CONFIG2, AD7380_CONFIG2_SDO, From patchwork Wed May 1 14:55:42 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Julien Stephan X-Patchwork-Id: 13650838 Received: from mail-wm1-f41.google.com (mail-wm1-f41.google.com [209.85.128.41]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 469741304B0 for ; Wed, 1 May 2024 14:56:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.41 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714575362; cv=none; b=Mxfx+G1aiNTvlbeQ0c5AOE3trdm4gW8G5PLos28hOk7QTZwZGLeRIV6lOf8Hwz5Yao97Px/+lSyVbdbC8r4KO5GzcidApEgSi3v7sHXtDZeWJ1uJoW2LzdCFBsucsvQGXHQksb1FVfs7g6aDKJYyrqMZDx1oCxezfmvvlTZAwAw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714575362; c=relaxed/simple; bh=du2kLMCRp5o4P3dsqZNBM0LPI3ROwsmwvCGStfPCr9g=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=ZdsQ1fiUwj1cmbVXNUVeg0uBe+FJbKk+QBGRWvUA9c45M9yb/MZG+WqqUwj32k4rQb+/zcXtPcX0/1HUPpHs93DSK0srQHyT8Tnv3NhonfBJ+Bl7ssxLaPrhy//vp9NjO4pBSJdtY5DJZVnjWEIKoOVo7Kr2AbhZ8ECFmJE+kHM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=baylibre.com; spf=pass smtp.mailfrom=baylibre.com; dkim=pass (2048-bit key) header.d=baylibre-com.20230601.gappssmtp.com header.i=@baylibre-com.20230601.gappssmtp.com header.b=poCE+KvX; arc=none smtp.client-ip=209.85.128.41 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=baylibre.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=baylibre-com.20230601.gappssmtp.com header.i=@baylibre-com.20230601.gappssmtp.com header.b="poCE+KvX" Received: by mail-wm1-f41.google.com with SMTP id 5b1f17b1804b1-41c7ac73fddso27494375e9.3 for ; Wed, 01 May 2024 07:56:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1714575358; x=1715180158; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=i7y0HuhKkWvqsIGNuF6QczDFqnvdiHcoO8fQ4/iNtzs=; b=poCE+KvXhN7uuuX0pL6L7JRYd9h9vqK1UHnrTDzk++aiDicsWFywc7ez/GkXK4ZUjL 1AyVEDpt1a4+dBFv1ZjrX2BEqjFK307WOHsa/uwIramawIeevpY/qtvAt2X0CiHg3gaf XLV06rcITfHvxHe6XY0ayB2SlGXw0KgTixAbDmiH1Po+15FKlVTpmWlGPBc7sdN7EpzV bRntg2hag9F9ny6KmdI6ZM566SO7O2thZMHlWME5G/7bRj4HxonC3hT0HQQhZARw58OP RjTRynWtIbIYjWJVRSXAqoaXbuv8Inx4zgdIMimR/9KbayEgrJ+aHr9JkVmv5KWbu6os PWXA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1714575359; x=1715180159; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=i7y0HuhKkWvqsIGNuF6QczDFqnvdiHcoO8fQ4/iNtzs=; b=GUu5C/GOfjFFP/7NMGp7W/J7bZl7UknCXGDue1Ji4wnzsV36SkP7/YOOWYl9noApWl XTD00T20+7Hy/ssa3VudEzMLEvGH4cSkUjTLhyN5PUEK+xBDUn1OSZiXeHJWeQIzA5j5 amImvDYCAfyT9+cHpSnLKxVSt0/e183UgYUw6Mqn98hBcT/XUyS9dxBZ5e47eQW7Rc/t QksejNvbmpIET4VNP/bdge8IjJ/yxvHYDdqD9aEt7y6i7ImI5Hd+BkfHomnuaG5Tes87 RgeBvuDu1gfLCYDsurYvF/gDt5776bt54xE/G9Tytpp6/7zuCfR6XZAYIrfAF1oqkIGi 8eoA== X-Forwarded-Encrypted: i=1; AJvYcCVqB/xU35Jt8EcIAHnujg4PHENIUhyMkhJXYAe5Fm2bH9FANSwdEQpvg1d+i1Cn6KLmERq5tCJdKVPufFv26H49qPJzyMqqO/R7 X-Gm-Message-State: AOJu0YwauHxw4D+/bjneNcDs+ypq/jgZuDZRsbP9HhuwOQZ8gIdfVJ3M PJ6SNE8LtXDRsXEJZRMs3TAQkVgqFZqu2gyFez0vibf9jHwf6vlPDVuXZOF0Uj0= X-Google-Smtp-Source: AGHT+IFb+S1JZu/pjS1R0VAFDljvVUvKkc6fdJz5V7dgS2gKjVI2x4U7x6KqVf5Hme/wx0vVVUAkjg== X-Received: by 2002:a05:600c:5250:b0:41c:b44:f917 with SMTP id fc16-20020a05600c525000b0041c0b44f917mr2595394wmb.22.1714575358698; Wed, 01 May 2024 07:55:58 -0700 (PDT) Received: from [192.168.1.61] ([2a02:842a:d52e:6101:6fd0:6c4:5d68:f0a5]) by smtp.gmail.com with ESMTPSA id o27-20020a05600c511b00b00418a386c17bsm2422999wms.12.2024.05.01.07.55.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 01 May 2024 07:55:58 -0700 (PDT) From: Julien Stephan Date: Wed, 01 May 2024 16:55:42 +0200 Subject: [PATCH RFC v6 09/10] iio: adc: ad7380: add support for rolling average oversampling mode Precedence: bulk X-Mailing-List: linux-iio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20240501-adding-new-ad738x-driver-v6-9-3c0741154728@baylibre.com> References: <20240501-adding-new-ad738x-driver-v6-0-3c0741154728@baylibre.com> In-Reply-To: <20240501-adding-new-ad738x-driver-v6-0-3c0741154728@baylibre.com> To: Lars-Peter Clausen , Michael Hennerich , =?utf-8?q?Nuno_S=C3=A1?= , David Lechner , Jonathan Cameron , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Liam Girdwood , Mark Brown Cc: kernel test robot , linux-iio@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Julien Stephan X-Mailer: b4 0.13.0 Adds support for rolling average oversampling mode. Rolling oversampling mode uses a first in, first out (FIFO) buffer of the most recent samples in the averaging calculation, allowing the ADC throughput rate and output data rate to stay the same, since we only need to take only one sample for each new conversion. The FIFO length is 8, thus the available oversampling ratios are 1, 2, 4, 8 in this mode (vs 1, 2, 4, 8, 16, 32 for the normal average) In order to be able to change the averaging mode, this commit also adds the new "oversampling_mode" and "oversampling_mode_available" custom attributes along with the according documentation file in Documentation/ABI/testing/sysfs-bus-iio-adc-ad7380 since no standard attributes correspond to this use case. Signed-off-by: Julien Stephan --- Documentation/ABI/testing/sysfs-bus-iio-adc-ad7380 | 38 ++++++ MAINTAINERS | 1 + drivers/iio/adc/ad7380.c | 143 +++++++++++++++++++-- 3 files changed, 174 insertions(+), 8 deletions(-) diff --git a/Documentation/ABI/testing/sysfs-bus-iio-adc-ad7380 b/Documentation/ABI/testing/sysfs-bus-iio-adc-ad7380 new file mode 100644 index 000000000000..0a560ef3e32a --- /dev/null +++ b/Documentation/ABI/testing/sysfs-bus-iio-adc-ad7380 @@ -0,0 +1,38 @@ +What: /sys/bus/iio/devices/iio:deviceX/oversampling_mode +KernelVersion: 6.9 +Contact: Michael Hennerich +Description: + Writing this attribute sets the oversampling average mode. + Reading it, shows the configured mode. + Available modes can be displayed using the oversampling_mode_available + attribute. + When writing this attribute to change the oversampling mode, this will + have the following side effects: + + - soft reset the ADC to flush the oversampling block and FIFO + + - the available oversampling ratios depend on the oversampling mode + configured so to avoid misconfiguration, changing the mode will disable + the oversampling by setting the ratio to 1. + + - the list of available ratios (displayed by reading the + oversampling_ratio_available attribute) will be updated when changing + the oversampling mode. + +What: /sys/bus/iio/devices/iio:deviceX/oversampling_mode_available +KernelVersion: 6.9 +Contact: Michael Hennerich +Description: + Display the available oversampling average modes. The two available modes + are "normal" and "rolling" where "normal" average mode is the default one. + + - normal averaging involves taking a number of samples, adding them + together, and dividing the result by the number of samples taken. + This result is then output from the device. The sample data is cleared + when the process completes. Because we need more samples to output a + value, the data output rate decrease with the oversampling ratio. + + - rolling oversampling mode uses a first in, first out (FIFO) buffer of + the most recent samples in the averaging calculation, allowing the ADC + throughput rate and output data rate to stay the same, since we only need + to take only one sample for each new conversion. diff --git a/MAINTAINERS b/MAINTAINERS index 87724a9e9f9f..ca1e115f2aff 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -434,6 +434,7 @@ R: David Lechner S: Supported W: https://wiki.analog.com/resources/tools-software/linux-drivers/iio-adc/ad738x W: https://ez.analog.com/linux-software-drivers +F: Documentation/ABI/testing/sysfs-bus-iio-adc-ad7380 F: Documentation/devicetree/bindings/iio/adc/adi,ad7380.yaml F: drivers/iio/adc/ad7380.c diff --git a/drivers/iio/adc/ad7380.c b/drivers/iio/adc/ad7380.c index 1e3869f5e48c..7b021bb9cf87 100644 --- a/drivers/iio/adc/ad7380.c +++ b/drivers/iio/adc/ad7380.c @@ -51,6 +51,8 @@ #define AD7380_REG_ADDR_ALERT_HIGH_TH 0x5 #define AD7380_CONFIG1_OS_MODE BIT(9) +#define OS_MODE_NORMAL_AVERAGE 0 +#define OS_MODE_ROLLING_AVERAGE 1 #define AD7380_CONFIG1_OSR GENMASK(8, 6) #define AD7380_CONFIG1_CRC_W BIT(5) #define AD7380_CONFIG1_CRC_R BIT(4) @@ -159,16 +161,27 @@ static const struct ad7380_timing_specs ad7380_4_timing = { .t_csh_ns = 20, }; +/* + * Available oversampling modes. + */ +static const char * const ad7380_oversampling_average_modes[] = { + [OS_MODE_NORMAL_AVERAGE] = "normal", + [OS_MODE_ROLLING_AVERAGE] = "rolling", +}; + /* * Available oversampling ratios. The indices correspond * with the bit value expected by the chip. - * The available ratios depend on the averaging mode, - * only normal averaging is supported for now + * The available ratios depend on the averaging mode. */ static const int ad7380_normal_average_oversampling_ratios[] = { 1, 2, 4, 8, 16, 32, }; +static const int ad7380_rolling_average_oversampling_ratios[] = { + 1, 2, 4, 8, +}; + static const struct ad7380_chip_info ad7380_chip_info = { .name = "ad7380", .channels = ad7380_channels, @@ -244,6 +257,7 @@ static const struct ad7380_chip_info ad7384_4_chip_info = { struct ad7380_state { const struct ad7380_chip_info *chip_info; struct spi_device *spi; + unsigned int oversampling_mode; unsigned int oversampling_ratio; struct regmap *regmap; unsigned int vref_mv; @@ -403,7 +417,7 @@ static int ad7380_read_direct(struct ad7380_state *st, /* * In normal average oversampling we need to wait for multiple conversions to be done */ - if (st->oversampling_ratio > 1) + if (st->oversampling_mode == OS_MODE_NORMAL_AVERAGE && st->oversampling_ratio > 1) xfers[0].delay.value = T_CONVERT_NS + 500 * st->oversampling_ratio; ret = spi_sync_transfer(st->spi, xfers, ARRAY_SIZE(xfers)); @@ -462,10 +476,22 @@ static int ad7380_read_avail(struct iio_dev *indio_dev, const int **vals, int *type, int *length, long mask) { + struct ad7380_state *st = iio_priv(indio_dev); + switch (mask) { case IIO_CHAN_INFO_OVERSAMPLING_RATIO: - *vals = ad7380_normal_average_oversampling_ratios; - *length = ARRAY_SIZE(ad7380_normal_average_oversampling_ratios); + switch (st->oversampling_mode) { + case OS_MODE_NORMAL_AVERAGE: + *vals = ad7380_normal_average_oversampling_ratios; + *length = ARRAY_SIZE(ad7380_normal_average_oversampling_ratios); + break; + case OS_MODE_ROLLING_AVERAGE: + *vals = ad7380_rolling_average_oversampling_ratios; + *length = ARRAY_SIZE(ad7380_rolling_average_oversampling_ratios); + break; + default: + return -EINVAL; + } *type = IIO_VAL_INT; return IIO_AVAIL_LIST; @@ -505,9 +531,20 @@ static int ad7380_write_raw(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_OVERSAMPLING_RATIO: - osr = check_osr(ad7380_normal_average_oversampling_ratios, - ARRAY_SIZE(ad7380_normal_average_oversampling_ratios), - val); + switch (st->oversampling_mode) { + case OS_MODE_NORMAL_AVERAGE: + osr = check_osr(ad7380_normal_average_oversampling_ratios, + ARRAY_SIZE(ad7380_normal_average_oversampling_ratios), + val); + break; + case OS_MODE_ROLLING_AVERAGE: + osr = check_osr(ad7380_rolling_average_oversampling_ratios, + ARRAY_SIZE(ad7380_rolling_average_oversampling_ratios), + val); + break; + default: + return -EINVAL; + } if (osr < 0) return osr; @@ -538,7 +575,96 @@ static int ad7380_write_raw(struct iio_dev *indio_dev, } } +static ssize_t oversampling_mode_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ad7380_state *st = iio_priv(dev_to_iio_dev(dev)); + unsigned int os_mode; + + os_mode = st->oversampling_mode; + + return sysfs_emit(buf, "%s\n", ad7380_oversampling_average_modes[os_mode]); +} + +static ssize_t oversampling_mode_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct ad7380_state *st = iio_priv(indio_dev); + int os_mode, ret; + + ret = sysfs_match_string(ad7380_oversampling_average_modes, buf); + if (ret < 0) + return ret; + + os_mode = ret; + + iio_device_claim_direct_scoped(return -EBUSY, indio_dev) { + ret = regmap_update_bits(st->regmap, AD7380_REG_ADDR_CONFIG1, + AD7380_CONFIG1_OS_MODE, + FIELD_PREP(AD7380_CONFIG1_OS_MODE, os_mode)); + + if (ret) + return ret; + + st->oversampling_mode = os_mode; + + /* + * Oversampling ratio depends on oversampling mode, to avoid + * misconfiguration when changing oversampling mode, + * disable oversampling by setting OSR to 0. + */ + ret = regmap_update_bits(st->regmap, AD7380_REG_ADDR_CONFIG1, + AD7380_CONFIG1_OSR, FIELD_PREP(AD7380_CONFIG1_OSR, 0)); + + if (ret) + return ret; + + st->oversampling_ratio = 1; + + /* + * Perform a soft reset. + * This will flush the oversampling block and FIFO but will + * maintain the content of the configurable registers. + */ + ret = regmap_update_bits(st->regmap, AD7380_REG_ADDR_CONFIG2, + AD7380_CONFIG2_RESET, + FIELD_PREP(AD7380_CONFIG2_RESET, + AD7380_CONFIG2_RESET_SOFT)); + } + return ret ?: len; +} + +static ssize_t oversampling_mode_available_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int i; + size_t len = 0; + + for (i = 0; i < ARRAY_SIZE(ad7380_oversampling_average_modes); i++) + len += sysfs_emit_at(buf, len, "%s ", ad7380_oversampling_average_modes[i]); + + buf[len - 1] = '\n'; + + return len; +} + +static IIO_DEVICE_ATTR_RW(oversampling_mode, 0); +static IIO_DEVICE_ATTR_RO(oversampling_mode_available, 0); + +static struct attribute *ad7380_attributes[] = { + &iio_dev_attr_oversampling_mode.dev_attr.attr, + &iio_dev_attr_oversampling_mode_available.dev_attr.attr, + NULL +}; + +static const struct attribute_group ad7380_attribute_group = { + .attrs = ad7380_attributes, +}; + static const struct iio_info ad7380_info = { + .attrs = &ad7380_attribute_group, .read_raw = &ad7380_read_raw, .read_avail = &ad7380_read_avail, .write_raw = &ad7380_write_raw, @@ -569,6 +695,7 @@ static int ad7380_init(struct ad7380_state *st, struct regulator *vref) * This is the default value after reset, * so just initialize internal data */ + st->oversampling_mode = OS_MODE_NORMAL_AVERAGE; st->oversampling_ratio = 1; /* SPI 1-wire mode */ From patchwork Wed May 1 14:55:43 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Julien Stephan X-Patchwork-Id: 13650839 Received: from mail-wm1-f53.google.com (mail-wm1-f53.google.com [209.85.128.53]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B619013048E for ; Wed, 1 May 2024 14:56:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.53 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714575364; cv=none; b=g4yMAsVUPCeHr46kWOfBx4MxIlchGVIH5qU6FAFvVwc7gCmAe5jxIzIv3lyvrXqYM6UdznuHfP341Ky0UccUxn3D8bF9clZnSeDexD31npN6GZFOTZNS1DKxaPTAf/P0k0948SFEatFt5V/1Ry/PM3Xk4YaxGu0pubnc2K0i2fw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714575364; c=relaxed/simple; bh=fPiWODpLyIpk8mbW8S6s/JMkotwnMO8eXB66C821A4Y=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=fmXXh4Yg+ccMNZXef8rcWDWglAZY6nxr51hKp9uc2hEZAKPs/8LsgEYb9p6RD+AWDAmTDUDofnD0q0UNRY4IUB3FsQ3ljdxmh52kjnfs99OpezXu1TVe2WQpOloFnkFWzZUMFtVHvKJ0l6ceVk9hzN0kSBGZvd74or3FP0ACCdo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=baylibre.com; spf=pass smtp.mailfrom=baylibre.com; dkim=pass (2048-bit key) header.d=baylibre-com.20230601.gappssmtp.com header.i=@baylibre-com.20230601.gappssmtp.com header.b=GpHwOJ+8; arc=none smtp.client-ip=209.85.128.53 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=baylibre.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=baylibre-com.20230601.gappssmtp.com header.i=@baylibre-com.20230601.gappssmtp.com header.b="GpHwOJ+8" Received: by mail-wm1-f53.google.com with SMTP id 5b1f17b1804b1-41b79451145so41799795e9.3 for ; Wed, 01 May 2024 07:56:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1714575360; x=1715180160; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=nQvEn6eTVpgZ7ge0YdIc6SxCVLT/jwgprRg33qL4bbM=; b=GpHwOJ+8ic/QRgOaFULe4pEsyJRBTLRHzpL6+HJs/LuHH6LX6a39AupxOfj6HFlacS meenSSYKKw6LCQzhwcmdYvKbMGvZAjWwLsartU9ndvsHxjoVaaaCFQ5kprmiDnP2qyWv lXlJJFeiMSM4WsCZKL4/QqBbgKooTRat1Xximzm2VCSxEo/byGSxFDEJO3RKYtRxXylr d5IVpzQcDSdYLOrzWvMkP/P/7jrfcktOg/8UsdUm8Q0/7q478KOEPp3pz0L0njXlKLXt pkF9ksHPl3Q0DMspWaOzXMXhA2E30oy7AnhCnOkUj78y31PXKClW0TJLfMqjccYx+iRP bG1Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1714575360; x=1715180160; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=nQvEn6eTVpgZ7ge0YdIc6SxCVLT/jwgprRg33qL4bbM=; b=SWzA/TIJZyBkRaFVTJw6r301RzFpFlAgkfH/5gdRsbkb7JqZ1lfDvnieTr3bFdkq2N 8cKZL4CMEQDQfAsYomnJOZZVYxBiUWK8UZsAaDEIZofrfiZp1BvmnL01CHUqUZhhxI3K z3A3FJEIe9OD3Mg8RdKP85n4euwSsMEF01zFFCYJN49Mpu4L+2OXillPZ87qOgzaPIWp 1iS4vuTH9sELs/FJzSUATLDArz4oltd3X9V8fkAOrrgwb4PeMGV3+HkH6K6+7mPjiCkf 2tZLhj6C8oQQcqNNeikWK0ReOc6p9BYi6S7rPfeXaZcJRNB2efKeqBJTIUTPNVoMzJnB hDKg== X-Forwarded-Encrypted: i=1; AJvYcCXqwlkOSVjfsUFSd3FCHXtLrOiHPi95pYAYQ3rP/yQicVCp9EAyy0fSiqLPJi8IffAnT4GL3MYapliY2W15LwMa0/TtSxpJpLto X-Gm-Message-State: AOJu0YxnWjh6ziBN0Ojv2o6Xx3/9c7IgTV4GzmqMgHWpLDbkRrsWtShx rlQcw3zGI5K/K8EZyYWJ9AsVCOqgfB+8C2/hFEqxB/XirOjKDnZmaGD2JVtsMmw= X-Google-Smtp-Source: AGHT+IFPiOA5OgO2LcEiOeQ9z95Elxo3H/VFN/MqqHOCNEN/VLCkZAllpFjJjc9lb1KKraoJW4trZQ== X-Received: by 2002:a05:600c:3148:b0:416:536b:683a with SMTP id h8-20020a05600c314800b00416536b683amr1823734wmo.32.1714575360127; Wed, 01 May 2024 07:56:00 -0700 (PDT) Received: from [192.168.1.61] ([2a02:842a:d52e:6101:6fd0:6c4:5d68:f0a5]) by smtp.gmail.com with ESMTPSA id o27-20020a05600c511b00b00418a386c17bsm2422999wms.12.2024.05.01.07.55.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 01 May 2024 07:55:59 -0700 (PDT) From: Julien Stephan Date: Wed, 01 May 2024 16:55:43 +0200 Subject: [PATCH RFC v6 10/10] iio: adc: ad7380: add support for resolution boost Precedence: bulk X-Mailing-List: linux-iio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20240501-adding-new-ad738x-driver-v6-10-3c0741154728@baylibre.com> References: <20240501-adding-new-ad738x-driver-v6-0-3c0741154728@baylibre.com> In-Reply-To: <20240501-adding-new-ad738x-driver-v6-0-3c0741154728@baylibre.com> To: Lars-Peter Clausen , Michael Hennerich , =?utf-8?q?Nuno_S=C3=A1?= , David Lechner , Jonathan Cameron , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Liam Girdwood , Mark Brown Cc: kernel test robot , linux-iio@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Julien Stephan X-Mailer: b4 0.13.0 ad738x chips are able to use an additional 2 bits of resolution when using oversampling. The 14-bits chips can have up to 16 bits of resolution and the 16-bits chips can have up to 18 bits of resolution. In order to dynamically allow to enable/disable the resolution boost feature, we have to set iio realbits/storagebits to the maximum per chips. This means that for iio, data will always be on the higher resolution available, and to cope with that we adjust the iio scale and iio offset depending on the resolution boost status. The available scales can be displayed using the regular _scale_available attributes and can be set by writing the regular _scale attribute. The available scales depend on the oversampling status. Signed-off-by: Julien Stephan --- In order to support the resolution boost (additional 2 bits of resolution) we need to set realbits/storagebits to the maximum value i.e : - realbits = 16 + 2 = 18, and storagebits = 32 for 16-bits chips - realbits = 14 + 2 = 16, and storagebits = 16 for 14-bits chips For 14-bits chips this does not have a major impact, but this has the drawback of forcing 16-bits chip users to always use 32-bits words in buffers even if they are not using oversampling and resolution boost. Is there a better way of implementing this? For example implementing dynamic scan_type? Another issue is the location of the timestamps. I understood the need for ts to be consistent between chips, but right now I do not have a better solution.. I was thinking of maybe adding the timestamps at the beginning? That would imply to change the iio_chan_spec struct and maybe add a iio_push_to_buffers_with_timestamp_first() wrapper function? Is that an option? Any suggestion would be very much appreciated. --- drivers/iio/adc/ad7380.c | 226 ++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 194 insertions(+), 32 deletions(-) diff --git a/drivers/iio/adc/ad7380.c b/drivers/iio/adc/ad7380.c index 7b021bb9cf87..e240098708e9 100644 --- a/drivers/iio/adc/ad7380.c +++ b/drivers/iio/adc/ad7380.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -58,6 +59,8 @@ #define AD7380_CONFIG1_CRC_R BIT(4) #define AD7380_CONFIG1_ALERTEN BIT(3) #define AD7380_CONFIG1_RES BIT(2) +#define RESOLUTION_BOOST_DISABLE 0 +#define RESOLUTION_BOOST_ENABLE 1 #define AD7380_CONFIG1_REFSEL BIT(1) #define AD7380_CONFIG1_PMODE BIT(0) @@ -86,6 +89,14 @@ struct ad7380_chip_info { const struct ad7380_timing_specs *timing_specs; }; +/* + * realbits/storagebits cannot be dynamically changed, so in order to + * support the resolution boost (additional 2 bits of resolution) + * we need to set realbits/storagebits to the maximum value i.e : + * - realbits = 16 + 2 = 18, and storagebits = 32 for 16-bits chips + * - realbits = 14 + 2 = 16, and storagebits = 16 for 14-bits chips + * We need to adjust the scale depending on resolution boost status + */ #define AD7380_CHANNEL(index, bits, diff) { \ .type = IIO_VOLTAGE, \ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ @@ -93,6 +104,7 @@ struct ad7380_chip_info { .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \ .info_mask_shared_by_type_available = \ + BIT(IIO_CHAN_INFO_SCALE) | \ BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \ .indexed = 1, \ .differential = (diff), \ @@ -101,8 +113,8 @@ struct ad7380_chip_info { .scan_index = (index), \ .scan_type = { \ .sign = 's', \ - .realbits = (bits), \ - .storagebits = 16, \ + .realbits = (bits) + 2, \ + .storagebits = ((bits) + 2 > 16) ? 32 : 16, \ .endianness = IIO_CPU, \ }, \ } @@ -259,6 +271,8 @@ struct ad7380_state { struct spi_device *spi; unsigned int oversampling_mode; unsigned int oversampling_ratio; + unsigned int scales[2][2]; + bool resolution_boost_enable; struct regmap *regmap; unsigned int vref_mv; unsigned int vcm_mv[MAX_NUM_CHANNELS]; @@ -270,7 +284,10 @@ struct ad7380_state { * As MAX_NUM_CHANNELS is 4 the layout of the structure is the same for all parts */ struct { - u16 raw[MAX_NUM_CHANNELS]; + union { + u16 u16[MAX_NUM_CHANNELS]; + u32 u32[MAX_NUM_CHANNELS]; + } raw; s64 ts __aligned(8); } scan_data __aligned(IIO_DMA_MINALIGN); @@ -359,23 +376,67 @@ static int ad7380_debugfs_reg_access(struct iio_dev *indio_dev, u32 reg, unreachable(); } +static int ad7380_prepare_spi_xfer(struct ad7380_state *st, struct spi_transfer *xfer) +{ + int bits_per_word; + + memset(xfer, 0, sizeof(*xfer)); + + xfer->rx_buf = &st->scan_data.raw; + + if (st->resolution_boost_enable == RESOLUTION_BOOST_ENABLE) + bits_per_word = st->chip_info->channels[0].scan_type.realbits; + else + bits_per_word = st->chip_info->channels[0].scan_type.realbits - 2; + + xfer->bits_per_word = bits_per_word; + + xfer->len = (st->chip_info->num_channels - 1) * BITS_TO_BYTES(bits_per_word); + + return bits_per_word; +} + static irqreturn_t ad7380_trigger_handler(int irq, void *p) { struct iio_poll_func *pf = p; struct iio_dev *indio_dev = pf->indio_dev; struct ad7380_state *st = iio_priv(indio_dev); - struct spi_transfer xfer = { - .bits_per_word = st->chip_info->channels[0].scan_type.realbits, - .len = (st->chip_info->num_channels - 1) * - BITS_TO_BYTES(st->chip_info->channels->scan_type.storagebits), - .rx_buf = st->scan_data.raw, - }; - int ret; + struct spi_transfer xfer; + int bits_per_word, realbits, i, ret; + + realbits = st->chip_info->channels[0].scan_type.realbits; + bits_per_word = ad7380_prepare_spi_xfer(st, &xfer); ret = spi_sync_transfer(st->spi, &xfer, 1); if (ret) goto out; + /* + * If bits_per_word == realbits (resolution boost enabled), we don't + * need to manipulate the raw data, otherwise we may need to fix things + * up a bit to fit the scan_type specs + */ + if (bits_per_word < realbits) { + if (realbits > 16 && bits_per_word <= 16) { + /* + * Here realbits > 16 so storagebits is 32 and bits_per_word is <= 16 + * so we need to sign extend u16 to u32 using reverse order to + * avoid writing over union data + */ + for (i = st->chip_info->num_channels - 2; i >= 0; i--) + st->scan_data.raw.u32[i] = sign_extend32(st->scan_data.raw.u16[i], + bits_per_word - 1); + } else if (bits_per_word < 16) { + /* + * Here realbits <= 16 so storagebits is 16. + * We only need to sign extend only if bits_per_word is < 16 + */ + for (i = 0; i < st->chip_info->num_channels - 1; i++) + st->scan_data.raw.u16[i] = sign_extend32(st->scan_data.raw.u16[i], + bits_per_word - 1); + } + } + iio_push_to_buffers_with_timestamp(indio_dev, &st->scan_data, pf->timestamp); @@ -388,7 +449,7 @@ static irqreturn_t ad7380_trigger_handler(int irq, void *p) static int ad7380_read_direct(struct ad7380_state *st, struct iio_chan_spec const *chan, int *val) { - struct spi_transfer xfers[] = { + struct spi_transfer xfers[2] = { /* toggle CS (no data xfer) to trigger a conversion */ { .speed_hz = AD7380_REG_WR_SPEED_HZ, @@ -403,16 +464,11 @@ static int ad7380_read_direct(struct ad7380_state *st, .unit = SPI_DELAY_UNIT_NSECS, }, }, - /* then read all channels */ + /* then read all channels, it will be filled by ad7380_prepare_spi_xfer */ { - .speed_hz = AD7380_REG_WR_SPEED_HZ, - .bits_per_word = chan->scan_type.realbits, - .rx_buf = st->scan_data.raw, - .len = (st->chip_info->num_channels - 1) * - ((chan->scan_type.storagebits > 16) ? 4 : 2), }, }; - int ret; + int bits_per_word, ret; /* * In normal average oversampling we need to wait for multiple conversions to be done @@ -420,12 +476,18 @@ static int ad7380_read_direct(struct ad7380_state *st, if (st->oversampling_mode == OS_MODE_NORMAL_AVERAGE && st->oversampling_ratio > 1) xfers[0].delay.value = T_CONVERT_NS + 500 * st->oversampling_ratio; + bits_per_word = ad7380_prepare_spi_xfer(st, &xfers[1]); + ret = spi_sync_transfer(st->spi, xfers, ARRAY_SIZE(xfers)); if (ret < 0) return ret; - *val = sign_extend32(st->scan_data.raw[chan->scan_index], - chan->scan_type.realbits - 1); + if (bits_per_word > 16) + *val = sign_extend32(st->scan_data.raw.u32[chan->scan_index], + bits_per_word - 1); + else + *val = sign_extend32(st->scan_data.raw.u16[chan->scan_index], + bits_per_word - 1); return IIO_VAL_INT; } @@ -435,6 +497,12 @@ static int ad7380_read_raw(struct iio_dev *indio_dev, int *val, int *val2, long info) { struct ad7380_state *st = iio_priv(indio_dev); + int realbits; + + if (st->resolution_boost_enable == RESOLUTION_BOOST_ENABLE) + realbits = chan->scan_type.realbits; + else + realbits = chan->scan_type.realbits - 2; switch (info) { case IIO_CHAN_INFO_RAW: @@ -443,22 +511,16 @@ static int ad7380_read_raw(struct iio_dev *indio_dev, } unreachable(); case IIO_CHAN_INFO_SCALE: - /* - * According to the datasheet, the LSB size is: - * * (2 × VREF) / 2^N, for differential chips - * * VREF / 2^N, for pseudo-differential chips - * where N is the ADC resolution (i.e realbits) - */ - *val = st->vref_mv; - *val2 = chan->scan_type.realbits - chan->differential; + *val = st->scales[st->resolution_boost_enable][0]; + *val2 = st->scales[st->resolution_boost_enable][1]; - return IIO_VAL_FRACTIONAL_LOG2; + return IIO_VAL_INT_PLUS_MICRO; case IIO_CHAN_INFO_OFFSET: /* * According to IIO ABI, offset is applied before scale, * so offset is: vcm_mv / scale */ - *val = st->vcm_mv[chan->channel] * (1 << chan->scan_type.realbits) + *val = st->vcm_mv[chan->channel] * (1 << realbits) / st->vref_mv; return IIO_VAL_INT; @@ -494,6 +556,24 @@ static int ad7380_read_avail(struct iio_dev *indio_dev, } *type = IIO_VAL_INT; + return IIO_AVAIL_LIST; + case IIO_CHAN_INFO_SCALE: + *vals = (const int *)st->scales[0]; + /* + * Values are stored into a 2D matrix. + * We have 2 available scales depending on the resolution boost status + * (enabled/disabled). Resolution boost can be enabled only when oversampling + * is enabled (i.e OSR > 1). + * So depending on the oversampling ratio we display only the currently + * available scales. First scale is for normal mode, second scale is for resolution + * boost enabled. + */ + if (st->oversampling_ratio > 1) + *length = 4; + else + *length = 2; + *type = IIO_VAL_INT_PLUS_MICRO; + return IIO_AVAIL_LIST; default: return -EINVAL; @@ -522,6 +602,25 @@ static inline int check_osr(const int *available_ratio, int size, int ratio) return -EINVAL; } +static int ad7380_set_resolution_boost(struct iio_dev *indio_dev, bool enable) +{ + struct ad7380_state *st = iio_priv(indio_dev); + int ret; + + if (st->resolution_boost_enable == enable) + return 0; + + ret = regmap_update_bits(st->regmap, AD7380_REG_ADDR_CONFIG1, + AD7380_CONFIG1_RES, + FIELD_PREP(AD7380_CONFIG1_RES, enable)); + + if (ret) + return ret; + + st->resolution_boost_enable = enable; + return 0; +} + static int ad7380_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int val, int val2, long mask) @@ -559,6 +658,13 @@ static int ad7380_write_raw(struct iio_dev *indio_dev, st->oversampling_ratio = val; + /* + * If oversampling is disabled (OSR == 1), + * we need to disable resolution boost + */ + if (st->oversampling_ratio == 1) + ad7380_set_resolution_boost(indio_dev, RESOLUTION_BOOST_DISABLE); + /* * Perform a soft reset. * This will flush the oversampling block and FIFO but will @@ -570,6 +676,25 @@ static int ad7380_write_raw(struct iio_dev *indio_dev, AD7380_CONFIG2_RESET_SOFT)); } return 0; + case IIO_CHAN_INFO_SCALE: + if (val == st->scales[RESOLUTION_BOOST_DISABLE][0] && + val2 == st->scales[RESOLUTION_BOOST_DISABLE][1]) { + iio_device_claim_direct_scoped(return -EBUSY, indio_dev) { + return ad7380_set_resolution_boost(indio_dev, + RESOLUTION_BOOST_DISABLE); + } + unreachable(); + } + if (st->oversampling_ratio > 1 && + val == st->scales[RESOLUTION_BOOST_ENABLE][0] && + val2 == st->scales[RESOLUTION_BOOST_ENABLE][1]) { + iio_device_claim_direct_scoped(return -EBUSY, indio_dev) { + return ad7380_set_resolution_boost(indio_dev, + RESOLUTION_BOOST_ENABLE); + } + unreachable(); + } + return -EINVAL; default: return -EINVAL; } @@ -614,6 +739,8 @@ static ssize_t oversampling_mode_store(struct device *dev, * Oversampling ratio depends on oversampling mode, to avoid * misconfiguration when changing oversampling mode, * disable oversampling by setting OSR to 0. + * Since we disable the oversampling, we also need to + * disable the resolution boost */ ret = regmap_update_bits(st->regmap, AD7380_REG_ADDR_CONFIG1, AD7380_CONFIG1_OSR, FIELD_PREP(AD7380_CONFIG1_OSR, 0)); @@ -622,6 +749,7 @@ static ssize_t oversampling_mode_store(struct device *dev, return ret; st->oversampling_ratio = 1; + ad7380_set_resolution_boost(indio_dev, RESOLUTION_BOOST_DISABLE); /* * Perform a soft reset. @@ -671,6 +799,36 @@ static const struct iio_info ad7380_info = { .debugfs_reg_access = &ad7380_debugfs_reg_access, }; +static void ad7380_init_available_scales(struct ad7380_state *st) +{ + s64 tmp; + int value_micro, value_int, realbits, differential; + + /* + * Resolution boost allow to enable 2 higher bits resolution + * when oversampling is enabled, so we can have only two + * scales depending on the resolution boost status. + */ + realbits = st->chip_info->channels[0].scan_type.realbits; + differential = st->chip_info->channels[0].differential; + + /* + * According to the datasheet, the LSB size is: + * * (2 × VREF) / 2^N, for differential chips + * * VREF / 2^N, for pseudo-differential chips + * where N is the ADC resolution (i.e realbits) + */ + tmp = (s64)st->vref_mv * MEGA >> (realbits - 2 - differential); + value_int = div_s64_rem(tmp, MEGA, &value_micro); + st->scales[RESOLUTION_BOOST_DISABLE][0] = value_int; + st->scales[RESOLUTION_BOOST_DISABLE][1] = value_micro; + + tmp = (s64)st->vref_mv * MEGA >> (realbits - differential); + value_int = div_s64_rem(tmp, MEGA, &value_micro); + st->scales[RESOLUTION_BOOST_ENABLE][0] = value_int; + st->scales[RESOLUTION_BOOST_ENABLE][1] = value_micro; +} + static int ad7380_init(struct ad7380_state *st, struct regulator *vref) { int ret; @@ -691,12 +849,16 @@ static int ad7380_init(struct ad7380_state *st, struct regulator *vref) if (ret < 0) return ret; - /* Disable oversampling by default. - * This is the default value after reset, + /* Disable oversampling and resolution boost by default. + * This are the default values after reset, * so just initialize internal data */ st->oversampling_mode = OS_MODE_NORMAL_AVERAGE; st->oversampling_ratio = 1; + st->resolution_boost_enable = RESOLUTION_BOOST_DISABLE; + + /* initialize available scales */ + ad7380_init_available_scales(st); /* SPI 1-wire mode */ return regmap_update_bits(st->regmap, AD7380_REG_ADDR_CONFIG2,