From nobody Mon Nov 25 19:41:51 2024 Received: from mail-lf1-f44.google.com (mail-lf1-f44.google.com [209.85.167.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 9A5441EC00B for ; Fri, 25 Oct 2024 09:51:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.167.44 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729849872; cv=none; b=DFM6C9PPc5rt2SrNzQb9uzgy4b2DrmtRmt85QBBQ8YmC04a9589qh8ZRZLx6pllzSWLypeRy0vpPkXUy8IFg54DKEmf18hvS9/43pccuABu162I4J2MT6UylDqk77PLR4h5pnZ3KNZk9JF3b6Gy8qoo//XMDTfOkO2Z7EhT3qfA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729849872; c=relaxed/simple; bh=z3pMsYq/WCjJ5cGi5DZHS/I9h7QpOytsVxUzZssEfU8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=gnnTflYKshxXGbuDj4CGYr1dXRNTpS1LqKUajxuCghiEOEfahiCVGULdEPSQ21qHKncQcqo/vOSz0gaGm2hO8h2dLvOUxMJxjAT7DY8H+21NtQ2yQJiQrM8htPXF3DKYquDjo9f0/3k33ZML/hl7Yli6sftth3IfMdclC1wvT0Y= 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=CjdFySvN; arc=none smtp.client-ip=209.85.167.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="CjdFySvN" Received: by mail-lf1-f44.google.com with SMTP id 2adb3069b0e04-539e6c754bdso1682863e87.2 for ; Fri, 25 Oct 2024 02:51:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1729849866; x=1730454666; 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=3LP2SK3ImgeSsfc3Kk3d1CrxyYM7oitcHbek/7ETa9o=; b=CjdFySvN+EDGjbOO8IA82ZswCOoqCo/ubjbquDhkAD6yJrrgPItgLcTAYP41NYjVbV 4Qh+MhOuiXqmfqfMn94jo1u5I63WqxbAqJf7X8wncgxd/YJPwvVpGBAitQXcgaiEuPQ2 UC/A43NWJKySU2hfSKdbMA49EoXN8n43PpVuCUBXrsIiAfOngwoRmR6vru+rzzl7MXKz WuIHUkZxiwSoULDgUQi8cdLnEPPQso62ydm1x394oKKP2bpac3487cnvbQwaYJV7rAip l7Tkj9Ug93RB3vRu5iSAw6thGu/wvYt+2lO4X4a7Vrov+jqG/2iAmGGt9PyaeNPPhewk Ci9g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1729849866; x=1730454666; 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=3LP2SK3ImgeSsfc3Kk3d1CrxyYM7oitcHbek/7ETa9o=; b=Hg+AltBR0VSknmuBtf0SUAdegMWKPD+UJqlVvtdmj/HM6QHgK1tVE+KFW0EAtcD7VN g9HjYpSnRUhY2FVvKQUTyLxwwiyErNFT2fne9Plm6PhdIclv41FD9Ya7diFh8jEs5KCW yOmDzeLCezFSEHInm11SmkK4F1zcF/DO5+NzTHy3uSZlgJkf1da6QR6ie4K9HUb1O/4i iarNWelS4qAX2HROPEABnn4kbKQl06WDiFA20fZrTI0tKiZSKLfcNhSmoMTPCZiEJdzN wxtJstc6tuaaL29IwHgikmVa3Oy8KDxwhwQsk2hqW+hoK+pGckFhv6iyW5Ll6C6acyMa nP2Q== X-Forwarded-Encrypted: i=1; AJvYcCVHGqLSe+1U6wqwIPOozBvPaf2r1uFNSsC7wylDOBmoFXd+fFzhc+V7wVgF70H8ompL2TupjPsD86H1AKs=@vger.kernel.org X-Gm-Message-State: AOJu0Yzf8vvtn59ULP6rIa65cGHi4KrpJQYN/yVfmLxbkNFF1bfh8WMw ih1++t9mal0nT69viDMbvMiPfeczLhwRXUti3o4PYExHtF5tzsTMX3adn4KpGOg= X-Google-Smtp-Source: AGHT+IGeKTIiekGEU2YXwtNJbKm4AdvByUFDKwaN7aLcVEwW3v81Sh+lpNL8Ji+hyT4LVxwJ6S+xrA== X-Received: by 2002:a05:651c:1508:b0:2fb:351c:c3c9 with SMTP id 38308e7fff4ca-2fc9d5982bdmr50368471fa.44.1729849865633; Fri, 25 Oct 2024 02:51:05 -0700 (PDT) Received: from [127.0.1.1] (host-79-41-194-153.retail.telecomitalia.it. [79.41.194.153]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-431935f6df1sm12895085e9.35.2024.10.25.02.51.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 25 Oct 2024 02:51:05 -0700 (PDT) From: Angelo Dureghello X-Google-Original-From: Angelo Dureghello Date: Fri, 25 Oct 2024 11:49:39 +0200 Subject: [PATCH v8 6/8] iio: dac: ad3552r: extract common code (no changes in behavior intended) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20241025-wip-bl-ad3552r-axi-v0-iio-testing-v8-6-74ca7dd60567@baylibre.com> References: <20241025-wip-bl-ad3552r-axi-v0-iio-testing-v8-0-74ca7dd60567@baylibre.com> In-Reply-To: <20241025-wip-bl-ad3552r-axi-v0-iio-testing-v8-0-74ca7dd60567@baylibre.com> To: Lars-Peter Clausen , Michael Hennerich , =?utf-8?q?Nuno_S=C3=A1?= , Jonathan Cameron , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Olivier Moysan Cc: linux-iio@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Mark Brown , dlechner@baylibre.com, Angelo Dureghello X-Mailer: b4 0.14.1 From: Angelo Dureghello Extracting common code, to share common code to be used later by the AXI driver version (ad3552r-axi.c). Signed-off-by: Angelo Dureghello --- drivers/iio/dac/Makefile | 2 +- drivers/iio/dac/ad3552r-common.c | 248 ++++++++++++++++++++++++ drivers/iio/dac/ad3552r.c | 398 +++--------------------------------= ---- drivers/iio/dac/ad3552r.h | 226 ++++++++++++++++++++++ 4 files changed, 502 insertions(+), 372 deletions(-) diff --git a/drivers/iio/dac/Makefile b/drivers/iio/dac/Makefile index 621d553bd6e3..c92de0366238 100644 --- a/drivers/iio/dac/Makefile +++ b/drivers/iio/dac/Makefile @@ -4,7 +4,7 @@ # =20 # When adding new entries keep the list in alphabetical order -obj-$(CONFIG_AD3552R) +=3D ad3552r.o +obj-$(CONFIG_AD3552R) +=3D ad3552r.o ad3552r-common.o obj-$(CONFIG_AD5360) +=3D ad5360.o obj-$(CONFIG_AD5380) +=3D ad5380.o obj-$(CONFIG_AD5421) +=3D ad5421.o diff --git a/drivers/iio/dac/ad3552r-common.c b/drivers/iio/dac/ad3552r-com= mon.c new file mode 100644 index 000000000000..672f0284bc05 --- /dev/null +++ b/drivers/iio/dac/ad3552r-common.c @@ -0,0 +1,248 @@ +// SPDX-License-Identifier: GPL-2.0+ +// +// Copyright (c) 2010-2024 Analog Devices Inc. +// Copyright (c) 2024 Baylibre, SAS + +#include +#include +#include +#include + +#include "ad3552r.h" + +const s32 ad3552r_ch_ranges[AD3552R_MAX_RANGES][2] =3D { + [AD3552R_CH_OUTPUT_RANGE_0__2P5V] =3D { 0, 2500 }, + [AD3552R_CH_OUTPUT_RANGE_0__5V] =3D { 0, 5000 }, + [AD3552R_CH_OUTPUT_RANGE_0__10V] =3D { 0, 10000 }, + [AD3552R_CH_OUTPUT_RANGE_NEG_5__5V] =3D { -5000, 5000 }, + [AD3552R_CH_OUTPUT_RANGE_NEG_10__10V] =3D { -10000, 10000 } +}; +EXPORT_SYMBOL_NS_GPL(ad3552r_ch_ranges, IIO_AD3552R); + +const s32 ad3542r_ch_ranges[AD3542R_MAX_RANGES][2] =3D { + [AD3542R_CH_OUTPUT_RANGE_0__2P5V] =3D { 0, 2500 }, + [AD3542R_CH_OUTPUT_RANGE_0__3V] =3D { 0, 3000 }, + [AD3542R_CH_OUTPUT_RANGE_0__5V] =3D { 0, 5000 }, + [AD3542R_CH_OUTPUT_RANGE_0__10V] =3D { 0, 10000 }, + [AD3542R_CH_OUTPUT_RANGE_NEG_2P5__7P5V] =3D { -2500, 7500 }, + [AD3542R_CH_OUTPUT_RANGE_NEG_5__5V] =3D { -5000, 5000 } +}; +EXPORT_SYMBOL_NS_GPL(ad3542r_ch_ranges, IIO_AD3552R); + +/* Gain * AD3552R_GAIN_SCALE */ +static const s32 gains_scaling_table[] =3D { + [AD3552R_CH_GAIN_SCALING_1] =3D 1000, + [AD3552R_CH_GAIN_SCALING_0_5] =3D 500, + [AD3552R_CH_GAIN_SCALING_0_25] =3D 250, + [AD3552R_CH_GAIN_SCALING_0_125] =3D 125 +}; + +u16 ad3552r_calc_custom_gain(u8 p, u8 n, s16 goffs) +{ + return FIELD_PREP(AD3552R_MASK_CH_RANGE_OVERRIDE, 1) | + FIELD_PREP(AD3552R_MASK_CH_GAIN_SCALING_P, p) | + FIELD_PREP(AD3552R_MASK_CH_GAIN_SCALING_N, n) | + FIELD_PREP(AD3552R_MASK_CH_OFFSET_BIT_8, abs(goffs)) | + FIELD_PREP(AD3552R_MASK_CH_OFFSET_POLARITY, goffs < 0); +} +EXPORT_SYMBOL_NS_GPL(ad3552r_calc_custom_gain, IIO_AD3552R); + +static void ad3552r_get_custom_range(struct ad3552r_ch_data *ch_data, + s32 *v_min, s32 *v_max) +{ + s64 vref, tmp, common, offset, gn, gp; + /* + * From datasheet formula (In Volts): + * Vmin =3D 2.5 + [(GainN + Offset / 1024) * 2.5 * Rfb * 1.03] + * Vmax =3D 2.5 - [(GainP + Offset / 1024) * 2.5 * Rfb * 1.03] + * Calculus are converted to milivolts + */ + vref =3D 2500; + /* 2.5 * 1.03 * 1000 (To mV) */ + common =3D 2575 * ch_data->rfb; + offset =3D ch_data->gain_offset; + + gn =3D gains_scaling_table[ch_data->n]; + tmp =3D (1024 * gn + AD3552R_GAIN_SCALE * offset) * common; + tmp =3D div_s64(tmp, 1024 * AD3552R_GAIN_SCALE); + *v_max =3D vref + tmp; + + gp =3D gains_scaling_table[ch_data->p]; + tmp =3D (1024 * gp - AD3552R_GAIN_SCALE * offset) * common; + tmp =3D div_s64(tmp, 1024 * AD3552R_GAIN_SCALE); + *v_min =3D vref - tmp; +} + +void ad3552r_calc_gain_and_offset(struct ad3552r_ch_data *ch_data, + const struct ad3552r_model_data *model_data) +{ + s32 idx, v_max, v_min, span, rem; + s64 tmp; + + if (ch_data->range_override) { + ad3552r_get_custom_range(ch_data, &v_min, &v_max); + } else { + /* Normal range */ + idx =3D ch_data->range; + v_min =3D model_data->ranges_table[idx][0]; + v_max =3D model_data->ranges_table[idx][1]; + } + + /* + * From datasheet formula: + * Vout =3D Span * (D / 65536) + Vmin + * Converted to scale and offset: + * Scale =3D Span / 65536 + * Offset =3D 65536 * Vmin / Span + * + * Reminders are in micros in order to be printed as + * IIO_VAL_INT_PLUS_MICRO + */ + span =3D v_max - v_min; + ch_data->scale_int =3D div_s64_rem(span, 65536, &rem); + /* Do operations in microvolts */ + ch_data->scale_dec =3D DIV_ROUND_CLOSEST((s64)rem * 1000000, 65536); + + ch_data->offset_int =3D div_s64_rem(v_min * 65536, span, &rem); + tmp =3D (s64)rem * 1000000; + ch_data->offset_dec =3D div_s64(tmp, span); +} +EXPORT_SYMBOL_NS_GPL(ad3552r_calc_gain_and_offset, IIO_AD3552R); + +int ad3552r_get_ref_voltage(struct device *dev, u32 *val) +{ + int voltage; + int delta =3D 100000; + + voltage =3D devm_regulator_get_enable_read_voltage(dev, "vref"); + if (voltage < 0 && voltage !=3D -ENODEV) + return dev_err_probe(dev, voltage, + "Error getting vref voltage\n"); + + if (voltage =3D=3D -ENODEV) { + if (device_property_read_bool(dev, "adi,vref-out-en")) + *val =3D AD3552R_INTERNAL_VREF_PIN_2P5V; + else + *val =3D AD3552R_INTERNAL_VREF_PIN_FLOATING; + + return 0; + } + + if (voltage > 2500000 + delta || voltage < 2500000 - delta) { + dev_warn(dev, "vref-supply must be 2.5V"); + return -EINVAL; + } + + *val =3D AD3552R_EXTERNAL_VREF_PIN_INPUT; + + return 0; +} +EXPORT_SYMBOL_NS_GPL(ad3552r_get_ref_voltage, IIO_AD3552R); + +int ad3552r_get_drive_strength(struct device *dev, u32 *val) +{ + int err; + u32 drive_strength; + + err =3D device_property_read_u32(dev, "adi,sdo-drive-strength", + &drive_strength); + if (err) + return err; + + if (drive_strength > 3) { + dev_err_probe(dev, -EINVAL, + "adi,sdo-drive-strength must be less than 4\n"); + return -EINVAL; + } + + *val =3D drive_strength; + + return 0; +} +EXPORT_SYMBOL_NS_GPL(ad3552r_get_drive_strength, IIO_AD3552R); + +int ad3552r_get_custom_gain(struct device *dev, struct fwnode_handle *chil= d, + u8 *gs_p, u8 *gs_n, u16 *rfb, s16 *goffs) +{ + int err; + u32 val; + struct fwnode_handle *gain_child __free(fwnode_handle) =3D + fwnode_get_named_child_node(child, + "custom-output-range-config"); + + if (!gain_child) + return dev_err_probe(dev, -EINVAL, + "custom-output-range-config mandatory\n"); + + err =3D fwnode_property_read_u32(gain_child, "adi,gain-scaling-p", &val); + if (err) + return dev_err_probe(dev, err, + "adi,gain-scaling-p mandatory\n"); + *gs_p =3D val; + + err =3D fwnode_property_read_u32(gain_child, "adi,gain-scaling-n", &val); + if (err) + return dev_err_probe(dev, err, + "adi,gain-scaling-n property mandatory\n"); + *gs_n =3D val; + + err =3D fwnode_property_read_u32(gain_child, "adi,rfb-ohms", &val); + if (err) + return dev_err_probe(dev, err, + "adi,rfb-ohms mandatory\n"); + *rfb =3D val; + + err =3D fwnode_property_read_u32(gain_child, "adi,gain-offset", &val); + if (err) + return dev_err_probe(dev, err, + "adi,gain-offset mandatory\n"); + *goffs =3D val; + + return 0; +} +EXPORT_SYMBOL_NS_GPL(ad3552r_get_custom_gain, IIO_AD3552R); + +static int ad3552r_find_range(const struct ad3552r_model_data *model_info, + s32 *vals) +{ + int i; + + for (i =3D 0; i < model_info->num_ranges; i++) + if (vals[0] =3D=3D model_info->ranges_table[i][0] * 1000 && + vals[1] =3D=3D model_info->ranges_table[i][1] * 1000) + return i; + + return -EINVAL; +} + +int ad3552r_get_output_range(struct device *dev, + const struct ad3552r_model_data *model_info, + struct fwnode_handle *child, u32 *val) +{ + int ret; + s32 vals[2]; + + /* This property is optional, so returning -ENOENT if missing */ + if (!fwnode_property_present(child, "adi,output-range-microvolt")) + return -ENOENT; + + ret =3D fwnode_property_read_u32_array(child, + "adi,output-range-microvolt", + vals, 2); + if (ret) + return dev_err_probe(dev, ret, + "invalid adi,output-range-microvolt\n"); + + ret =3D ad3552r_find_range(model_info, vals); + if (ret < 0) + return dev_err_probe(dev, ret, + "invalid adi,output-range-microvolt value\n"); + + *val =3D ret; + + return 0; +} +EXPORT_SYMBOL_NS_GPL(ad3552r_get_output_range, IIO_AD3552R); + +MODULE_DESCRIPTION("ad3552r common functions"); +MODULE_LICENSE("GPL"); diff --git a/drivers/iio/dac/ad3552r.c b/drivers/iio/dac/ad3552r.c index 75825d6a398b..bbfb451a5da1 100644 --- a/drivers/iio/dac/ad3552r.c +++ b/drivers/iio/dac/ad3552r.c @@ -11,226 +11,9 @@ #include #include #include -#include #include =20 -/* Register addresses */ -/* Primary address space */ -#define AD3552R_REG_ADDR_INTERFACE_CONFIG_A 0x00 -#define AD3552R_MASK_SOFTWARE_RESET (BIT(7) | BIT(0)) -#define AD3552R_MASK_ADDR_ASCENSION BIT(5) -#define AD3552R_MASK_SDO_ACTIVE BIT(4) -#define AD3552R_REG_ADDR_INTERFACE_CONFIG_B 0x01 -#define AD3552R_MASK_SINGLE_INST BIT(7) -#define AD3552R_MASK_SHORT_INSTRUCTION BIT(3) -#define AD3552R_REG_ADDR_DEVICE_CONFIG 0x02 -#define AD3552R_MASK_DEVICE_STATUS(n) BIT(4 + (n)) -#define AD3552R_MASK_CUSTOM_MODES GENMASK(3, 2) -#define AD3552R_MASK_OPERATING_MODES GENMASK(1, 0) -#define AD3552R_REG_ADDR_CHIP_TYPE 0x03 -#define AD3552R_MASK_CLASS GENMASK(7, 0) -#define AD3552R_REG_ADDR_PRODUCT_ID_L 0x04 -#define AD3552R_REG_ADDR_PRODUCT_ID_H 0x05 -#define AD3552R_REG_ADDR_CHIP_GRADE 0x06 -#define AD3552R_MASK_GRADE GENMASK(7, 4) -#define AD3552R_MASK_DEVICE_REVISION GENMASK(3, 0) -#define AD3552R_REG_ADDR_SCRATCH_PAD 0x0A -#define AD3552R_REG_ADDR_SPI_REVISION 0x0B -#define AD3552R_REG_ADDR_VENDOR_L 0x0C -#define AD3552R_REG_ADDR_VENDOR_H 0x0D -#define AD3552R_REG_ADDR_STREAM_MODE 0x0E -#define AD3552R_MASK_LENGTH GENMASK(7, 0) -#define AD3552R_REG_ADDR_TRANSFER_REGISTER 0x0F -#define AD3552R_MASK_MULTI_IO_MODE GENMASK(7, 6) -#define AD3552R_MASK_STREAM_LENGTH_KEEP_VALUE BIT(2) -#define AD3552R_REG_ADDR_INTERFACE_CONFIG_C 0x10 -#define AD3552R_MASK_CRC_ENABLE (GENMASK(7, 6) |\ - GENMASK(1, 0)) -#define AD3552R_MASK_STRICT_REGISTER_ACCESS BIT(5) -#define AD3552R_REG_ADDR_INTERFACE_STATUS_A 0x11 -#define AD3552R_MASK_INTERFACE_NOT_READY BIT(7) -#define AD3552R_MASK_CLOCK_COUNTING_ERROR BIT(5) -#define AD3552R_MASK_INVALID_OR_NO_CRC BIT(3) -#define AD3552R_MASK_WRITE_TO_READ_ONLY_REGISTER BIT(2) -#define AD3552R_MASK_PARTIAL_REGISTER_ACCESS BIT(1) -#define AD3552R_MASK_REGISTER_ADDRESS_INVALID BIT(0) -#define AD3552R_REG_ADDR_INTERFACE_CONFIG_D 0x14 -#define AD3552R_MASK_ALERT_ENABLE_PULLUP BIT(6) -#define AD3552R_MASK_MEM_CRC_EN BIT(4) -#define AD3552R_MASK_SDO_DRIVE_STRENGTH GENMASK(3, 2) -#define AD3552R_MASK_DUAL_SPI_SYNCHROUNOUS_EN BIT(1) -#define AD3552R_MASK_SPI_CONFIG_DDR BIT(0) -#define AD3552R_REG_ADDR_SH_REFERENCE_CONFIG 0x15 -#define AD3552R_MASK_IDUMP_FAST_MODE BIT(6) -#define AD3552R_MASK_SAMPLE_HOLD_DIFFERENTIAL_USER_EN BIT(5) -#define AD3552R_MASK_SAMPLE_HOLD_USER_TRIM GENMASK(4, 3) -#define AD3552R_MASK_SAMPLE_HOLD_USER_ENABLE BIT(2) -#define AD3552R_MASK_REFERENCE_VOLTAGE_SEL GENMASK(1, 0) -#define AD3552R_REG_ADDR_ERR_ALARM_MASK 0x16 -#define AD3552R_MASK_REF_RANGE_ALARM BIT(6) -#define AD3552R_MASK_CLOCK_COUNT_ERR_ALARM BIT(5) -#define AD3552R_MASK_MEM_CRC_ERR_ALARM BIT(4) -#define AD3552R_MASK_SPI_CRC_ERR_ALARM BIT(3) -#define AD3552R_MASK_WRITE_TO_READ_ONLY_ALARM BIT(2) -#define AD3552R_MASK_PARTIAL_REGISTER_ACCESS_ALARM BIT(1) -#define AD3552R_MASK_REGISTER_ADDRESS_INVALID_ALARM BIT(0) -#define AD3552R_REG_ADDR_ERR_STATUS 0x17 -#define AD3552R_MASK_REF_RANGE_ERR_STATUS BIT(6) -#define AD3552R_MASK_DUAL_SPI_STREAM_EXCEEDS_DAC_ERR_STATUS BIT(5) -#define AD3552R_MASK_MEM_CRC_ERR_STATUS BIT(4) -#define AD3552R_MASK_RESET_STATUS BIT(0) -#define AD3552R_REG_ADDR_POWERDOWN_CONFIG 0x18 -#define AD3552R_MASK_CH_DAC_POWERDOWN(ch) BIT(4 + (ch)) -#define AD3552R_MASK_CH_AMPLIFIER_POWERDOWN(ch) BIT(ch) -#define AD3552R_REG_ADDR_CH0_CH1_OUTPUT_RANGE 0x19 -#define AD3552R_MASK_CH_OUTPUT_RANGE_SEL(ch) ((ch) ? GENMASK(7, 4) :\ - GENMASK(3, 0)) -#define AD3552R_REG_ADDR_CH_OFFSET(ch) (0x1B + (ch) * 2) -#define AD3552R_MASK_CH_OFFSET_BITS_0_7 GENMASK(7, 0) -#define AD3552R_REG_ADDR_CH_GAIN(ch) (0x1C + (ch) * 2) -#define AD3552R_MASK_CH_RANGE_OVERRIDE BIT(7) -#define AD3552R_MASK_CH_GAIN_SCALING_N GENMASK(6, 5) -#define AD3552R_MASK_CH_GAIN_SCALING_P GENMASK(4, 3) -#define AD3552R_MASK_CH_OFFSET_POLARITY BIT(2) -#define AD3552R_MASK_CH_OFFSET_BIT_8 BIT(0) -/* - * Secondary region - * For multibyte registers specify the highest address because the access = is - * done in descending order - */ -#define AD3552R_SECONDARY_REGION_START 0x28 -#define AD3552R_REG_ADDR_HW_LDAC_16B 0x28 -#define AD3552R_REG_ADDR_CH_DAC_16B(ch) (0x2C - (1 - ch) * 2) -#define AD3552R_REG_ADDR_DAC_PAGE_MASK_16B 0x2E -#define AD3552R_REG_ADDR_CH_SELECT_16B 0x2F -#define AD3552R_REG_ADDR_INPUT_PAGE_MASK_16B 0x31 -#define AD3552R_REG_ADDR_SW_LDAC_16B 0x32 -#define AD3552R_REG_ADDR_CH_INPUT_16B(ch) (0x36 - (1 - ch) * 2) -/* 3 bytes registers */ -#define AD3552R_REG_START_24B 0x37 -#define AD3552R_REG_ADDR_HW_LDAC_24B 0x37 -#define AD3552R_REG_ADDR_CH_DAC_24B(ch) (0x3D - (1 - ch) * 3) -#define AD3552R_REG_ADDR_DAC_PAGE_MASK_24B 0x40 -#define AD3552R_REG_ADDR_CH_SELECT_24B 0x41 -#define AD3552R_REG_ADDR_INPUT_PAGE_MASK_24B 0x44 -#define AD3552R_REG_ADDR_SW_LDAC_24B 0x45 -#define AD3552R_REG_ADDR_CH_INPUT_24B(ch) (0x4B - (1 - ch) * 3) - -/* Useful defines */ -#define AD3552R_MAX_CH 2 -#define AD3552R_MASK_CH(ch) BIT(ch) -#define AD3552R_MASK_ALL_CH GENMASK(1, 0) -#define AD3552R_MAX_REG_SIZE 3 -#define AD3552R_READ_BIT BIT(7) -#define AD3552R_ADDR_MASK GENMASK(6, 0) -#define AD3552R_MASK_DAC_12B 0xFFF0 -#define AD3552R_DEFAULT_CONFIG_B_VALUE 0x8 -#define AD3552R_SCRATCH_PAD_TEST_VAL1 0x34 -#define AD3552R_SCRATCH_PAD_TEST_VAL2 0xB2 -#define AD3552R_GAIN_SCALE 1000 -#define AD3552R_LDAC_PULSE_US 100 - -enum ad3552r_ch_vref_select { - /* Internal source with Vref I/O floating */ - AD3552R_INTERNAL_VREF_PIN_FLOATING, - /* Internal source with Vref I/O at 2.5V */ - AD3552R_INTERNAL_VREF_PIN_2P5V, - /* External source with Vref I/O as input */ - AD3552R_EXTERNAL_VREF_PIN_INPUT -}; - -enum ad3552r_id { - AD3541R_ID =3D 0x400b, - AD3542R_ID =3D 0x4009, - AD3551R_ID =3D 0x400a, - AD3552R_ID =3D 0x4008, -}; - -enum ad3552r_ch_output_range { - /* Range from 0 V to 2.5 V. Requires Rfb1x connection */ - AD3552R_CH_OUTPUT_RANGE_0__2P5V, - /* Range from 0 V to 5 V. Requires Rfb1x connection */ - AD3552R_CH_OUTPUT_RANGE_0__5V, - /* Range from 0 V to 10 V. Requires Rfb2x connection */ - AD3552R_CH_OUTPUT_RANGE_0__10V, - /* Range from -5 V to 5 V. Requires Rfb2x connection */ - AD3552R_CH_OUTPUT_RANGE_NEG_5__5V, - /* Range from -10 V to 10 V. Requires Rfb4x connection */ - AD3552R_CH_OUTPUT_RANGE_NEG_10__10V, -}; - -static const s32 ad3552r_ch_ranges[][2] =3D { - [AD3552R_CH_OUTPUT_RANGE_0__2P5V] =3D {0, 2500}, - [AD3552R_CH_OUTPUT_RANGE_0__5V] =3D {0, 5000}, - [AD3552R_CH_OUTPUT_RANGE_0__10V] =3D {0, 10000}, - [AD3552R_CH_OUTPUT_RANGE_NEG_5__5V] =3D {-5000, 5000}, - [AD3552R_CH_OUTPUT_RANGE_NEG_10__10V] =3D {-10000, 10000} -}; - -enum ad3542r_ch_output_range { - /* Range from 0 V to 2.5 V. Requires Rfb1x connection */ - AD3542R_CH_OUTPUT_RANGE_0__2P5V, - /* Range from 0 V to 3 V. Requires Rfb1x connection */ - AD3542R_CH_OUTPUT_RANGE_0__3V, - /* Range from 0 V to 5 V. Requires Rfb1x connection */ - AD3542R_CH_OUTPUT_RANGE_0__5V, - /* Range from 0 V to 10 V. Requires Rfb2x connection */ - AD3542R_CH_OUTPUT_RANGE_0__10V, - /* Range from -2.5 V to 7.5 V. Requires Rfb2x connection */ - AD3542R_CH_OUTPUT_RANGE_NEG_2P5__7P5V, - /* Range from -5 V to 5 V. Requires Rfb2x connection */ - AD3542R_CH_OUTPUT_RANGE_NEG_5__5V, -}; - -static const s32 ad3542r_ch_ranges[][2] =3D { - [AD3542R_CH_OUTPUT_RANGE_0__2P5V] =3D {0, 2500}, - [AD3542R_CH_OUTPUT_RANGE_0__3V] =3D {0, 3000}, - [AD3542R_CH_OUTPUT_RANGE_0__5V] =3D {0, 5000}, - [AD3542R_CH_OUTPUT_RANGE_0__10V] =3D {0, 10000}, - [AD3542R_CH_OUTPUT_RANGE_NEG_2P5__7P5V] =3D {-2500, 7500}, - [AD3542R_CH_OUTPUT_RANGE_NEG_5__5V] =3D {-5000, 5000} -}; - -enum ad3552r_ch_gain_scaling { - /* Gain scaling of 1 */ - AD3552R_CH_GAIN_SCALING_1, - /* Gain scaling of 0.5 */ - AD3552R_CH_GAIN_SCALING_0_5, - /* Gain scaling of 0.25 */ - AD3552R_CH_GAIN_SCALING_0_25, - /* Gain scaling of 0.125 */ - AD3552R_CH_GAIN_SCALING_0_125, -}; - -/* Gain * AD3552R_GAIN_SCALE */ -static const s32 gains_scaling_table[] =3D { - [AD3552R_CH_GAIN_SCALING_1] =3D 1000, - [AD3552R_CH_GAIN_SCALING_0_5] =3D 500, - [AD3552R_CH_GAIN_SCALING_0_25] =3D 250, - [AD3552R_CH_GAIN_SCALING_0_125] =3D 125 -}; - -struct ad3552r_ch_data { - s32 scale_int; - s32 scale_dec; - s32 offset_int; - s32 offset_dec; - s16 gain_offset; - u16 rfb; - u8 n; - u8 p; - u8 range; - bool range_override; -}; - -struct ad3552r_model_data { - const char *model_name; - enum ad3552r_id chip_id; - unsigned int num_hw_channels; - const s32 (*ranges_table)[2]; - int num_ranges; - bool requires_output_range; -}; +#include "ad3552r.h" =20 struct ad3552r_desc { const struct ad3552r_model_data *model_data; @@ -632,136 +415,35 @@ static int ad3552r_reset(struct ad3552r_desc *dac) FIELD_PREP(AD3552R_MASK_ADDR_ASCENSION, val)); } =20 -static void ad3552r_get_custom_range(struct ad3552r_desc *dac, s32 i, s32 = *v_min, - s32 *v_max) -{ - s64 vref, tmp, common, offset, gn, gp; - /* - * From datasheet formula (In Volts): - * Vmin =3D 2.5 + [(GainN + Offset / 1024) * 2.5 * Rfb * 1.03] - * Vmax =3D 2.5 - [(GainP + Offset / 1024) * 2.5 * Rfb * 1.03] - * Calculus are converted to milivolts - */ - vref =3D 2500; - /* 2.5 * 1.03 * 1000 (To mV) */ - common =3D 2575 * dac->ch_data[i].rfb; - offset =3D dac->ch_data[i].gain_offset; - - gn =3D gains_scaling_table[dac->ch_data[i].n]; - tmp =3D (1024 * gn + AD3552R_GAIN_SCALE * offset) * common; - tmp =3D div_s64(tmp, 1024 * AD3552R_GAIN_SCALE); - *v_max =3D vref + tmp; - - gp =3D gains_scaling_table[dac->ch_data[i].p]; - tmp =3D (1024 * gp - AD3552R_GAIN_SCALE * offset) * common; - tmp =3D div_s64(tmp, 1024 * AD3552R_GAIN_SCALE); - *v_min =3D vref - tmp; -} - -static void ad3552r_calc_gain_and_offset(struct ad3552r_desc *dac, s32 ch) -{ - s32 idx, v_max, v_min, span, rem; - s64 tmp; - - if (dac->ch_data[ch].range_override) { - ad3552r_get_custom_range(dac, ch, &v_min, &v_max); - } else { - /* Normal range */ - idx =3D dac->ch_data[ch].range; - v_min =3D dac->model_data->ranges_table[idx][0]; - v_max =3D dac->model_data->ranges_table[idx][1]; - } - - /* - * From datasheet formula: - * Vout =3D Span * (D / 65536) + Vmin - * Converted to scale and offset: - * Scale =3D Span / 65536 - * Offset =3D 65536 * Vmin / Span - * - * Reminders are in micros in order to be printed as - * IIO_VAL_INT_PLUS_MICRO - */ - span =3D v_max - v_min; - dac->ch_data[ch].scale_int =3D div_s64_rem(span, 65536, &rem); - /* Do operations in microvolts */ - dac->ch_data[ch].scale_dec =3D DIV_ROUND_CLOSEST((s64)rem * 1000000, - 65536); - - dac->ch_data[ch].offset_int =3D div_s64_rem(v_min * 65536, span, &rem); - tmp =3D (s64)rem * 1000000; - dac->ch_data[ch].offset_dec =3D div_s64(tmp, span); -} - -static int ad3552r_find_range(const struct ad3552r_model_data *model_data, - s32 *vals) -{ - int i; - - for (i =3D 0; i < model_data->num_ranges; i++) - if (vals[0] =3D=3D model_data->ranges_table[i][0] * 1000 && - vals[1] =3D=3D model_data->ranges_table[i][1] * 1000) - return i; - - return -EINVAL; -} - static int ad3552r_configure_custom_gain(struct ad3552r_desc *dac, struct fwnode_handle *child, u32 ch) { struct device *dev =3D &dac->spi->dev; - u32 val; int err; u8 addr; - u16 reg =3D 0, offset; - - struct fwnode_handle *gain_child __free(fwnode_handle) - =3D fwnode_get_named_child_node(child, - "custom-output-range-config"); - if (!gain_child) - return dev_err_probe(dev, -EINVAL, - "mandatory custom-output-range-config property missing\n"); - - dac->ch_data[ch].range_override =3D 1; - reg |=3D FIELD_PREP(AD3552R_MASK_CH_RANGE_OVERRIDE, 1); - - err =3D fwnode_property_read_u32(gain_child, "adi,gain-scaling-p", &val); - if (err) - return dev_err_probe(dev, err, - "mandatory adi,gain-scaling-p property missing\n"); - reg |=3D FIELD_PREP(AD3552R_MASK_CH_GAIN_SCALING_P, val); - dac->ch_data[ch].p =3D val; - - err =3D fwnode_property_read_u32(gain_child, "adi,gain-scaling-n", &val); - if (err) - return dev_err_probe(dev, err, - "mandatory adi,gain-scaling-n property missing\n"); - reg |=3D FIELD_PREP(AD3552R_MASK_CH_GAIN_SCALING_N, val); - dac->ch_data[ch].n =3D val; - - err =3D fwnode_property_read_u32(gain_child, "adi,rfb-ohms", &val); - if (err) - return dev_err_probe(dev, err, - "mandatory adi,rfb-ohms property missing\n"); - dac->ch_data[ch].rfb =3D val; + u16 reg; =20 - err =3D fwnode_property_read_u32(gain_child, "adi,gain-offset", &val); + err =3D ad3552r_get_custom_gain(dev, child, + &dac->ch_data[ch].p, + &dac->ch_data[ch].n, + &dac->ch_data[ch].rfb, + &dac->ch_data[ch].gain_offset); if (err) - return dev_err_probe(dev, err, - "mandatory adi,gain-offset property missing\n"); - dac->ch_data[ch].gain_offset =3D val; + return err; =20 - offset =3D abs((s32)val); - reg |=3D FIELD_PREP(AD3552R_MASK_CH_OFFSET_BIT_8, (offset >> 8)); + dac->ch_data[ch].range_override =3D 1; =20 - reg |=3D FIELD_PREP(AD3552R_MASK_CH_OFFSET_POLARITY, (s32)val < 0); addr =3D AD3552R_REG_ADDR_CH_GAIN(ch); err =3D ad3552r_write_reg(dac, addr, - offset & AD3552R_MASK_CH_OFFSET_BITS_0_7); + abs((s32)dac->ch_data[ch].gain_offset) & + AD3552R_MASK_CH_OFFSET_BITS_0_7); if (err) return dev_err_probe(dev, err, "Error writing register\n"); =20 + reg =3D ad3552r_calc_custom_gain(dac->ch_data[ch].p, dac->ch_data[ch].n, + dac->ch_data[ch].gain_offset); + err =3D ad3552r_write_reg(dac, addr, reg); if (err) return dev_err_probe(dev, err, "Error writing register\n"); @@ -772,30 +454,17 @@ static int ad3552r_configure_custom_gain(struct ad355= 2r_desc *dac, static int ad3552r_configure_device(struct ad3552r_desc *dac) { struct device *dev =3D &dac->spi->dev; - int err, cnt =3D 0, voltage, delta =3D 100000; - u32 vals[2], val, ch; + int err, cnt =3D 0; + u32 val, ch; =20 dac->gpio_ldac =3D devm_gpiod_get_optional(dev, "ldac", GPIOD_OUT_HIGH); if (IS_ERR(dac->gpio_ldac)) return dev_err_probe(dev, PTR_ERR(dac->gpio_ldac), "Error getting gpio ldac"); =20 - voltage =3D devm_regulator_get_enable_read_voltage(dev, "vref"); - if (voltage < 0 && voltage !=3D -ENODEV) - return dev_err_probe(dev, voltage, "Error getting vref voltage\n"); - - if (voltage =3D=3D -ENODEV) { - if (device_property_read_bool(dev, "adi,vref-out-en")) - val =3D AD3552R_INTERNAL_VREF_PIN_2P5V; - else - val =3D AD3552R_INTERNAL_VREF_PIN_FLOATING; - } else { - if (voltage > 2500000 + delta || voltage < 2500000 - delta) { - dev_warn(dev, "vref-supply must be 2.5V"); - return -EINVAL; - } - val =3D AD3552R_EXTERNAL_VREF_PIN_INPUT; - } + err =3D ad3552r_get_ref_voltage(dev, &val); + if (err < 0) + return err; =20 err =3D ad3552r_update_reg_field(dac, AD3552R_REG_ADDR_SH_REFERENCE_CONFIG, @@ -804,13 +473,8 @@ static int ad3552r_configure_device(struct ad3552r_des= c *dac) if (err) return err; =20 - err =3D device_property_read_u32(dev, "adi,sdo-drive-strength", &val); + err =3D ad3552r_get_drive_strength(dev, &val); if (!err) { - if (val > 3) { - dev_err(dev, "adi,sdo-drive-strength must be less than 4\n"); - return -EINVAL; - } - err =3D ad3552r_update_reg_field(dac, AD3552R_REG_ADDR_INTERFACE_CONFIG_D, AD3552R_MASK_SDO_DRIVE_STRENGTH, @@ -835,21 +499,12 @@ static int ad3552r_configure_device(struct ad3552r_de= sc *dac) "reg must be less than %d\n", dac->model_data->num_hw_channels); =20 - if (fwnode_property_present(child, "adi,output-range-microvolt")) { - err =3D fwnode_property_read_u32_array(child, - "adi,output-range-microvolt", - vals, - 2); - if (err) - return dev_err_probe(dev, err, - "adi,output-range-microvolt property could not be parsed\n"); - - err =3D ad3552r_find_range(dac->model_data, vals); - if (err < 0) - return dev_err_probe(dev, err, - "Invalid adi,output-range-microvolt value\n"); + err =3D ad3552r_get_output_range(dev, dac->model_data, + child, &val); + if (err && err !=3D -ENOENT) + return err; =20 - val =3D err; + if (!err) { if (ch =3D=3D 0) val =3D FIELD_PREP(AD3552R_MASK_CH_OUTPUT_RANGE_SEL(0), val); else @@ -873,7 +528,7 @@ static int ad3552r_configure_device(struct ad3552r_desc= *dac) return err; } =20 - ad3552r_calc_gain_and_offset(dac, ch); + ad3552r_calc_gain_and_offset(&dac->ch_data[ch], dac->model_data); dac->enabled_ch |=3D BIT(ch); =20 if (ch =3D=3D 0) @@ -1072,3 +727,4 @@ module_spi_driver(ad3552r_driver); MODULE_AUTHOR("Mihail Chindris "); MODULE_DESCRIPTION("Analog Device AD3552R DAC"); MODULE_LICENSE("GPL v2"); +MODULE_IMPORT_NS(IIO_AD3552R); diff --git a/drivers/iio/dac/ad3552r.h b/drivers/iio/dac/ad3552r.h new file mode 100644 index 000000000000..22bd9ad27c65 --- /dev/null +++ b/drivers/iio/dac/ad3552r.h @@ -0,0 +1,226 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * AD3552R Digital <-> Analog converters common header + * + * Copyright 2021-2024 Analog Devices Inc. + * Author: Angelo Dureghello + */ + +#ifndef __DRIVERS_IIO_DAC_AD3552R_H__ +#define __DRIVERS_IIO_DAC_AD3552R_H__ + +/* Register addresses */ +/* Primary address space */ +#define AD3552R_REG_ADDR_INTERFACE_CONFIG_A 0x00 +#define AD3552R_MASK_SOFTWARE_RESET (BIT(7) | BIT(0)) +#define AD3552R_MASK_ADDR_ASCENSION BIT(5) +#define AD3552R_MASK_SDO_ACTIVE BIT(4) +#define AD3552R_REG_ADDR_INTERFACE_CONFIG_B 0x01 +#define AD3552R_MASK_SINGLE_INST BIT(7) +#define AD3552R_MASK_SHORT_INSTRUCTION BIT(3) +#define AD3552R_REG_ADDR_DEVICE_CONFIG 0x02 +#define AD3552R_MASK_DEVICE_STATUS(n) BIT(4 + (n)) +#define AD3552R_MASK_CUSTOM_MODES GENMASK(3, 2) +#define AD3552R_MASK_OPERATING_MODES GENMASK(1, 0) +#define AD3552R_REG_ADDR_CHIP_TYPE 0x03 +#define AD3552R_MASK_CLASS GENMASK(7, 0) +#define AD3552R_REG_ADDR_PRODUCT_ID_L 0x04 +#define AD3552R_REG_ADDR_PRODUCT_ID_H 0x05 +#define AD3552R_REG_ADDR_CHIP_GRADE 0x06 +#define AD3552R_MASK_GRADE GENMASK(7, 4) +#define AD3552R_MASK_DEVICE_REVISION GENMASK(3, 0) +#define AD3552R_REG_ADDR_SCRATCH_PAD 0x0A +#define AD3552R_REG_ADDR_SPI_REVISION 0x0B +#define AD3552R_REG_ADDR_VENDOR_L 0x0C +#define AD3552R_REG_ADDR_VENDOR_H 0x0D +#define AD3552R_REG_ADDR_STREAM_MODE 0x0E +#define AD3552R_MASK_LENGTH GENMASK(7, 0) +#define AD3552R_REG_ADDR_TRANSFER_REGISTER 0x0F +#define AD3552R_MASK_MULTI_IO_MODE GENMASK(7, 6) +#define AD3552R_MASK_STREAM_LENGTH_KEEP_VALUE BIT(2) +#define AD3552R_REG_ADDR_INTERFACE_CONFIG_C 0x10 +#define AD3552R_MASK_CRC_ENABLE (GENMASK(7, 6) |\ + GENMASK(1, 0)) +#define AD3552R_MASK_STRICT_REGISTER_ACCESS BIT(5) +#define AD3552R_REG_ADDR_INTERFACE_STATUS_A 0x11 +#define AD3552R_MASK_INTERFACE_NOT_READY BIT(7) +#define AD3552R_MASK_CLOCK_COUNTING_ERROR BIT(5) +#define AD3552R_MASK_INVALID_OR_NO_CRC BIT(3) +#define AD3552R_MASK_WRITE_TO_READ_ONLY_REGISTER BIT(2) +#define AD3552R_MASK_PARTIAL_REGISTER_ACCESS BIT(1) +#define AD3552R_MASK_REGISTER_ADDRESS_INVALID BIT(0) +#define AD3552R_REG_ADDR_INTERFACE_CONFIG_D 0x14 +#define AD3552R_MASK_ALERT_ENABLE_PULLUP BIT(6) +#define AD3552R_MASK_MEM_CRC_EN BIT(4) +#define AD3552R_MASK_SDO_DRIVE_STRENGTH GENMASK(3, 2) +#define AD3552R_MASK_DUAL_SPI_SYNCHROUNOUS_EN BIT(1) +#define AD3552R_MASK_SPI_CONFIG_DDR BIT(0) +#define AD3552R_REG_ADDR_SH_REFERENCE_CONFIG 0x15 +#define AD3552R_MASK_IDUMP_FAST_MODE BIT(6) +#define AD3552R_MASK_SAMPLE_HOLD_DIFF_USER_EN BIT(5) +#define AD3552R_MASK_SAMPLE_HOLD_USER_TRIM GENMASK(4, 3) +#define AD3552R_MASK_SAMPLE_HOLD_USER_ENABLE BIT(2) +#define AD3552R_MASK_REFERENCE_VOLTAGE_SEL GENMASK(1, 0) +#define AD3552R_REG_ADDR_ERR_ALARM_MASK 0x16 +#define AD3552R_MASK_REF_RANGE_ALARM BIT(6) +#define AD3552R_MASK_CLOCK_COUNT_ERR_ALARM BIT(5) +#define AD3552R_MASK_MEM_CRC_ERR_ALARM BIT(4) +#define AD3552R_MASK_SPI_CRC_ERR_ALARM BIT(3) +#define AD3552R_MASK_WRITE_TO_READ_ONLY_ALARM BIT(2) +#define AD3552R_MASK_PARTIAL_REGISTER_ACCESS_ALARM BIT(1) +#define AD3552R_MASK_REGISTER_ADDRESS_INVALID_ALARM BIT(0) +#define AD3552R_REG_ADDR_ERR_STATUS 0x17 +#define AD3552R_MASK_REF_RANGE_ERR_STATUS BIT(6) +#define AD3552R_MASK_STREAM_EXCEEDS_DAC_ERR_STATUS BIT(5) +#define AD3552R_MASK_MEM_CRC_ERR_STATUS BIT(4) +#define AD3552R_MASK_RESET_STATUS BIT(0) +#define AD3552R_REG_ADDR_POWERDOWN_CONFIG 0x18 +#define AD3552R_MASK_CH_DAC_POWERDOWN(ch) BIT(4 + (ch)) +#define AD3552R_MASK_CH_AMPLIFIER_POWERDOWN(ch) BIT(ch) +#define AD3552R_REG_ADDR_CH0_CH1_OUTPUT_RANGE 0x19 +#define AD3552R_MASK_CH0_RANGE GENMASK(2, 0) +#define AD3552R_MASK_CH1_RANGE GENMASK(6, 4) +#define AD3552R_MASK_CH_OUTPUT_RANGE GENMASK(7, 0) +#define AD3552R_MASK_CH_OUTPUT_RANGE_SEL(ch) ((ch) ? \ + GENMASK(7, 4) : \ + GENMASK(3, 0)) +#define AD3552R_REG_ADDR_CH_OFFSET(ch) (0x1B + (ch) * 2) +#define AD3552R_MASK_CH_OFFSET_BITS_0_7 GENMASK(7, 0) +#define AD3552R_REG_ADDR_CH_GAIN(ch) (0x1C + (ch) * 2) +#define AD3552R_MASK_CH_RANGE_OVERRIDE BIT(7) +#define AD3552R_MASK_CH_GAIN_SCALING_N GENMASK(6, 5) +#define AD3552R_MASK_CH_GAIN_SCALING_P GENMASK(4, 3) +#define AD3552R_MASK_CH_OFFSET_POLARITY BIT(2) +#define AD3552R_MASK_CH_OFFSET_BIT_8 BIT(8) +/* + * Secondary region + * For multibyte registers specify the highest address because the access = is + * done in descending order + */ +#define AD3552R_SECONDARY_REGION_START 0x28 +#define AD3552R_REG_ADDR_HW_LDAC_16B 0x28 +#define AD3552R_REG_ADDR_CH_DAC_16B(ch) (0x2C - (1 - (ch)) * 2) +#define AD3552R_REG_ADDR_DAC_PAGE_MASK_16B 0x2E +#define AD3552R_REG_ADDR_CH_SELECT_16B 0x2F +#define AD3552R_REG_ADDR_INPUT_PAGE_MASK_16B 0x31 +#define AD3552R_REG_ADDR_SW_LDAC_16B 0x32 +#define AD3552R_REG_ADDR_CH_INPUT_16B(ch) (0x36 - (1 - (ch)) * 2) +/* 3 bytes registers */ +#define AD3552R_REG_START_24B 0x37 +#define AD3552R_REG_ADDR_HW_LDAC_24B 0x37 +#define AD3552R_REG_ADDR_CH_DAC_24B(ch) (0x3D - (1 - (ch)) * 3) +#define AD3552R_REG_ADDR_DAC_PAGE_MASK_24B 0x40 +#define AD3552R_REG_ADDR_CH_SELECT_24B 0x41 +#define AD3552R_REG_ADDR_INPUT_PAGE_MASK_24B 0x44 +#define AD3552R_REG_ADDR_SW_LDAC_24B 0x45 +#define AD3552R_REG_ADDR_CH_INPUT_24B(ch) (0x4B - (1 - (ch)) * 3) + +/* Useful defines */ +#define AD3552R_MAX_CH 2 +#define AD3552R_MASK_CH(ch) BIT(ch) +#define AD3552R_MASK_ALL_CH GENMASK(1, 0) +#define AD3552R_MAX_REG_SIZE 3 +#define AD3552R_READ_BIT BIT(7) +#define AD3552R_ADDR_MASK GENMASK(6, 0) +#define AD3552R_MASK_DAC_12B GENMASK(15, 4) +#define AD3552R_DEFAULT_CONFIG_B_VALUE 0x8 +#define AD3552R_SCRATCH_PAD_TEST_VAL1 0x34 +#define AD3552R_SCRATCH_PAD_TEST_VAL2 0xB2 +#define AD3552R_GAIN_SCALE 1000 +#define AD3552R_LDAC_PULSE_US 100 + +#define AD3552R_MAX_RANGES 5 +#define AD3542R_MAX_RANGES 6 + +extern const s32 ad3552r_ch_ranges[AD3552R_MAX_RANGES][2]; +extern const s32 ad3542r_ch_ranges[AD3542R_MAX_RANGES][2]; + +enum ad3552r_id { + AD3541R_ID =3D 0x400b, + AD3542R_ID =3D 0x4009, + AD3551R_ID =3D 0x400a, + AD3552R_ID =3D 0x4008, +}; + +struct ad3552r_model_data { + const char *model_name; + enum ad3552r_id chip_id; + unsigned int num_hw_channels; + const s32 (*ranges_table)[2]; + int num_ranges; + bool requires_output_range; +}; + +struct ad3552r_ch_data { + s32 scale_int; + s32 scale_dec; + s32 offset_int; + s32 offset_dec; + s16 gain_offset; + u16 rfb; + u8 n; + u8 p; + u8 range; + bool range_override; +}; + +enum ad3552r_ch_gain_scaling { + /* Gain scaling of 1 */ + AD3552R_CH_GAIN_SCALING_1, + /* Gain scaling of 0.5 */ + AD3552R_CH_GAIN_SCALING_0_5, + /* Gain scaling of 0.25 */ + AD3552R_CH_GAIN_SCALING_0_25, + /* Gain scaling of 0.125 */ + AD3552R_CH_GAIN_SCALING_0_125, +}; + +enum ad3552r_ch_vref_select { + /* Internal source with Vref I/O floating */ + AD3552R_INTERNAL_VREF_PIN_FLOATING, + /* Internal source with Vref I/O at 2.5V */ + AD3552R_INTERNAL_VREF_PIN_2P5V, + /* External source with Vref I/O as input */ + AD3552R_EXTERNAL_VREF_PIN_INPUT +}; + +enum ad3542r_ch_output_range { + /* Range from 0 V to 2.5 V. Requires Rfb1x connection */ + AD3542R_CH_OUTPUT_RANGE_0__2P5V, + /* Range from 0 V to 3 V. Requires Rfb1x connection */ + AD3542R_CH_OUTPUT_RANGE_0__3V, + /* Range from 0 V to 5 V. Requires Rfb1x connection */ + AD3542R_CH_OUTPUT_RANGE_0__5V, + /* Range from 0 V to 10 V. Requires Rfb2x connection */ + AD3542R_CH_OUTPUT_RANGE_0__10V, + /* Range from -2.5 V to 7.5 V. Requires Rfb2x connection */ + AD3542R_CH_OUTPUT_RANGE_NEG_2P5__7P5V, + /* Range from -5 V to 5 V. Requires Rfb2x connection */ + AD3542R_CH_OUTPUT_RANGE_NEG_5__5V, +}; + +enum ad3552r_ch_output_range { + /* Range from 0 V to 2.5 V. Requires Rfb1x connection */ + AD3552R_CH_OUTPUT_RANGE_0__2P5V, + /* Range from 0 V to 5 V. Requires Rfb1x connection */ + AD3552R_CH_OUTPUT_RANGE_0__5V, + /* Range from 0 V to 10 V. Requires Rfb2x connection */ + AD3552R_CH_OUTPUT_RANGE_0__10V, + /* Range from -5 V to 5 V. Requires Rfb2x connection */ + AD3552R_CH_OUTPUT_RANGE_NEG_5__5V, + /* Range from -10 V to 10 V. Requires Rfb4x connection */ + AD3552R_CH_OUTPUT_RANGE_NEG_10__10V, +}; + +int ad3552r_get_output_range(struct device *dev, + const struct ad3552r_model_data *model_info, + struct fwnode_handle *child, u32 *val); +int ad3552r_get_custom_gain(struct device *dev, struct fwnode_handle *chil= d, + u8 *gs_p, u8 *gs_n, u16 *rfb, s16 *goffs); +u16 ad3552r_calc_custom_gain(u8 p, u8 n, s16 goffs); +int ad3552r_get_ref_voltage(struct device *dev, u32 *val); +int ad3552r_get_drive_strength(struct device *dev, u32 *val); +void ad3552r_calc_gain_and_offset(struct ad3552r_ch_data *ch_data, + const struct ad3552r_model_data *model_data); + +#endif /* __DRIVERS_IIO_DAC_AD3552R_H__ */ --=20 2.45.0.rc1