Received: by 2002:ab2:6a05:0:b0:1f8:1780:a4ed with SMTP id w5csp1158920lqo; Sat, 11 May 2024 09:44:47 -0700 (PDT) X-Forwarded-Encrypted: i=3; AJvYcCVSxEJ93vwAwVOpbwUMHqHz43i5uCVo3X1dbG/4eNgaVxdTEm3Gp0F94TMDJji28xA6vLgUuV3dM2SyLzvnLrScF5EmvBbjwVkGWyxVyA== X-Google-Smtp-Source: AGHT+IFh0ZQRTg1L55VkbjxLOjUnOnPf+LOacaTLia1qO3UWFQ8jVU+AA1DD62Nx0vO4TvSG3QM2 X-Received: by 2002:a17:903:110f:b0:1ea:b125:81a2 with SMTP id d9443c01a7336-1ef44161e50mr71475925ad.53.1715445887414; Sat, 11 May 2024 09:44:47 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1715445887; cv=pass; d=google.com; s=arc-20160816; b=jFlGHdfwoFEq1RWQ4WUupzfLLiKCgtl7/77s9+janZhjbwpYmWRLc5cvyFb2f+Lh+F lAu9DeiJDsaIbabJ/Quei6gVx4eZR6Zj4gemmYYBQA6GUkh9Qc1hmsz90xwiL0JbCFhA HDnpqZ+y1NjK3AMT/zWQu3zDhCUFkhQZ9VlZlRvzzCu1ZDib3Xx7ASFuBrh8rxARuJqT wrf9rGr2aZm3Ete690eKW6tbD2QdmHrthcpNR5KKvX4aztaoGWsP7Qu5J/jopf5ZuN1h xOgVDlhKa+Yb/QcD0LDeBFp6Jo8AiwVsvG+csUFkejYcyqlhSQiv8y7zKIaKBQ0xfLaX ZTLw== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:references:in-reply-to:message-id :subject:cc:to:from:date:dkim-signature; bh=hvYkvHvUbY/jFo3xftGzo/Jdzm+eSWOq0SpCNIBfzbc=; fh=l6z4lBzxR8WdpHkjaK6PN7LkYzIWyG5OXYi8Wq/QB7E=; b=O+db7S5KYevvZyIeoFy12ilQqyWaAjWuqsz5t6S/24/CVlkbbPWx/tHdd6lWRPrFLY QVYmUMGMS27sULnES8qD7poVXfrDqbz6qdngpoWi48U+o3jDZ93RtLG6d0XXt7Z23Xmi MCkgpwF1FJvhYAhx6TaZKgS57uqA+3hY8BZcSyy26hFUpyxmU86z5QJXaK2urfv0PNV2 g0Er6rQt/d8cjUvx2Vfil78Vc/RYEsL++xp2aLQpM1Fwd4xtMgSuvxOn1bHxldN/Z1ul kLmowZUb0VeqAqWNZecg00yoliGHabDBpzmqhKbEhIcZn2cceKCxGB3nDj6rMbekPa3+ JW8w==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=HCDD7E2n; arc=pass (i=1 dkim=pass dkdomain=kernel.org); spf=pass (google.com: domain of linux-kernel+bounces-176648-linux.lists.archive=gmail.com@vger.kernel.org designates 139.178.88.99 as permitted sender) smtp.mailfrom="linux-kernel+bounces-176648-linux.lists.archive=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from sv.mirrors.kernel.org (sv.mirrors.kernel.org. [139.178.88.99]) by mx.google.com with ESMTPS id d9443c01a7336-1ef0bf31496si58936085ad.214.2024.05.11.09.44.47 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 11 May 2024 09:44:47 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel+bounces-176648-linux.lists.archive=gmail.com@vger.kernel.org designates 139.178.88.99 as permitted sender) client-ip=139.178.88.99; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=HCDD7E2n; arc=pass (i=1 dkim=pass dkdomain=kernel.org); spf=pass (google.com: domain of linux-kernel+bounces-176648-linux.lists.archive=gmail.com@vger.kernel.org designates 139.178.88.99 as permitted sender) smtp.mailfrom="linux-kernel+bounces-176648-linux.lists.archive=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sv.mirrors.kernel.org (Postfix) with ESMTPS id 5156F280EC6 for ; Sat, 11 May 2024 16:44:29 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 38BFD1B7F7; Sat, 11 May 2024 16:44:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="HCDD7E2n" Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 01DE37F; Sat, 11 May 2024 16:44:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715445860; cv=none; b=IP909ElqADTfUQbQrd/5mHQyy2qOFKUjc+Mb0Ew2yDeYdvit9HhevWA9MTQiROGzZ3X34+za8NHslev45j6/GdOfEth6iUBmSha29XSnk3u4AMbbfS9JJQuILY7s/JjNS9FVSg6zS2rxU19GYBuGvCPirCutTx7WuqWGw6NxV5Y= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715445860; c=relaxed/simple; bh=qDXgVQofl6xyMBerDDNaa7UF3HpCSL+u555/Dv4UeLQ=; h=Date:From:To:Cc:Subject:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=tA22q28jnVi6tDJ8LMVzkoENB6Ct7DPPeWluOdmjVHrBZMbrKJSXPmleICyPrNAL4sBUR4kUL/jqxGmEeEVA8OAAxsNwTBQla7enkNWJy3V114g0krh+Ivjt0B5V1xgt3RpB+uuz3bbSZoUBXGe8Ux2CMg+lGCGP7jbE2YkMY1Y= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=HCDD7E2n; arc=none smtp.client-ip=10.30.226.201 Received: by smtp.kernel.org (Postfix) with ESMTPSA id 510D6C2BBFC; Sat, 11 May 2024 16:44:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1715445859; bh=qDXgVQofl6xyMBerDDNaa7UF3HpCSL+u555/Dv4UeLQ=; h=Date:From:To:Cc:Subject:In-Reply-To:References:From; b=HCDD7E2nF1/4zbRd7/4LZ0/4ULct/pvGJ0mxX70v+6WvQEwOw8ytnhaC0WlK8stK8 eNtIHzjtyvKnb06cyIvmoeb4DWoLsl8J+LW2rURMFid2GGKFvJ/N+GpUOWm+sZs/7S sBas5UnJP74HDI/YpKqpViDkcCe+9ROfWbkOAzmMi4lr8IJZbfCZaxkwX9hyfzBQCd k0y/Wgdhybndi8WNeqpQidAylgFUM08xjeeb+hTUH94DQuFoPCs9h7AyO/kKpX+0aT YrczQcw18SEP9p/xMwo2k3u9QIYB9y7os00RD0hIrx1p9Gn5IX8SNOcof79//8K7Xa 3vOwwr3JNAIXg== Date: Sat, 11 May 2024 17:44:05 +0100 From: Jonathan Cameron To: Mariel Tinaco Cc: , , , Lars-Peter Clausen , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Liam Girdwood , Mark Brown , Michael Hennerich , Marcelo Schmitt , Dimitri Fedrau , Guenter Roeck Subject: Re: [PATCH 2/2] iio: dac: support the ad8460 Waveform DAC Message-ID: <20240511174405.10d7fce8@jic23-huawei> In-Reply-To: <20240510064053.278257-3-Mariel.Tinaco@analog.com> References: <20240510064053.278257-1-Mariel.Tinaco@analog.com> <20240510064053.278257-3-Mariel.Tinaco@analog.com> X-Mailer: Claws Mail 4.2.0 (GTK 3.24.41; x86_64-pc-linux-gnu) 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 On Fri, 10 May 2024 14:40:53 +0800 Mariel Tinaco wrote: > The AD8460 is a =E2=80=9Cbits in, power out=E2=80=9D high voltage, high-p= ower, > highspeed driver optimized for large output current (up to =C2=B11 A) > and high slew rate (up to =C2=B11800 V/=CE=BCs) at high voltage (up to = =C2=B140 V) > into capacitive loads. >=20 > A digital engine implements user-configurable features: modes for > digital input, programmable supply current, and fault monitoring > and programmable protection settings for output current, > output voltage, and junction temperature. The AD8460 operates on > high voltage dual supplies up to =C2=B155 V and a single low voltage > supply of 5 V. >=20 > Signed-off-by: Mariel Tinaco I'd like to see some ABI docs for the debugfs interface. The device is unusual enough that a general intro document or a lot more in the series cover letter would be useful. I'm not sure what the dmaengine usage in here is doing for example? Driving the parallel bus perhaps? David was correct that the binding should reflect that part as well. I was assuming you'd only implemented the spi part. How to handle the pattern generator is also an interesting question. That probably wants a version of the symbol interfaces we use for PSK and similar. We did have some DDS drivers a long time back in staging but they only did a few fixed waveforms so this is breaking new ground. Having looked a little at the datasheet, we may want to hard code some limits - or get them from DT. Probably a bit too easy to set things on fire otherwise. Also, seems that this is only partly implemented. Please make that clear in the patch description. Perhaps this should have been an RFC with a list of questions? Jonathan > diff --git a/drivers/iio/dac/ad8460.c b/drivers/iio/dac/ad8460.c > new file mode 100644 > index 000000000..4049be0f5 > --- /dev/null > +++ b/drivers/iio/dac/ad8460.c > @@ -0,0 +1,652 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * AD8460 Waveform generator DAC Driver > + * > + * Copyright (C) 2024 Analog Devices, Inc. > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#define AD8460_CTRL_REG(x) (x) > +#define AD8460_HVDAC_DATA_WORD_LOW(x) (0x60 + (2 * (x))) > +#define AD8460_HVDAC_DATA_WORD_HIGH(x) (0x61 + (2 * (x))) > + > +#define AD8460_HV_RESET_MSK BIT(7) > +#define AD8460_HV_SLEEP_MSK BIT(4) > +#define AD8460_WAVE_GEN_MODE_MSK BIT(0) > + > +#define AD8460_HVDAC_SLEEP_MSK BIT(3) > + > +#define AD8460_APG_MODE_ENABLE_MSK BIT(5) > +#define AD8460_PATTERN_DEPTH_MSK GENMASK(3, 0) > + > +#define AD8460_SHUTDOWN_FLAG_MSK BIT(7) > +#define AD8460_DATA_BYTE_LOW_MSK GENMASK(7, 0) > +#define AD8460_DATA_BYTE_HIGH_MSK GENMASK(5, 0) > + > +#define AD8460_NOMINAL_VOLTAGE_SPAN 80 > +#define AD8460_MIN_VREFIO_UV 120000 > +#define AD8460_MAX_VREFIO_UV 1200000 > +#define AD8460_MIN_RSET_OHMS 2000 > +#define AD8460_MAX_RSET_OHMS 20000 > + > +struct ad8460_state { > + struct spi_device *spi; > + struct regmap *regmap; > + struct clk *sync_clk; > + /* lock to protect against multiple access to the device and shared dat= a */ > + struct mutex lock; > + u32 cache_apg_idx; > + u32 rset_ohms; > + int vref_mv; > +}; > + > + > +static const char * const ad8460_powerdown_modes[] =3D { > + "three_state", > +}; > + > +static int ad8460_get_powerdown_mode(struct iio_dev *indio_dev, > + const struct iio_chan_spec *chan) > +{ > + return 0; Why have the stubs in here? > +} > + > +static int ad8460_set_powerdown_mode(struct iio_dev *indio_dev, > + const struct iio_chan_spec *chan, > + unsigned int type) > +{ > + return 0; > +} > + > +static int ad8460_get_hvdac_byte(struct ad8460_state *state, byte? Seems to be getting a 14 bit value. > + int index, > + int *val) > +{ > + unsigned int high, low; > + int ret; > + > + ret =3D regmap_read(state->regmap, AD8460_HVDAC_DATA_WORD_HIGH(index), > + &high); Use a bulk read? Then byteswap if necessary and mask the result. > + if (ret) > + return ret; > + > + ret =3D regmap_read(state->regmap, AD8460_HVDAC_DATA_WORD_LOW(index), > + &low); > + if (ret) > + return ret; > + > + *val =3D FIELD_GET(AD8460_DATA_BYTE_HIGH_MSK, high) << 8 | low; > + > + return ret; > +} > + > +static int ad8460_set_hvdac_byte(struct ad8460_state *state, > + int index, > + int val) > +{ > + int ret; > + > + ret =3D regmap_write(state->regmap, AD8460_HVDAC_DATA_WORD_LOW(index), > + (val & 0xFF)); > + if (ret) > + return ret; > + > + return regmap_write(state->regmap, AD8460_HVDAC_DATA_WORD_HIGH(index), > + ((val >> 8) & 0xFF)); bulk write? or do these need to be ordered? > +} > + > +static int ad8460_set_sample(struct ad8460_state *state, int val) > +{ > + int ret; > + > + ret =3D ad8460_enable_apg_mode(state, 1); > + if (ret) > + return ret; > + > + guard(mutex)(&state->lock); > + ret =3D ad8460_set_hvdac_byte(state, 0, val); > + if (ret) > + return ret; > + > + return regmap_update_bits(state->regmap, > + AD8460_CTRL_REG(0x02), > + AD8460_PATTERN_DEPTH_MSK, > + FIELD_PREP(AD8460_PATTERN_DEPTH_MSK, 0)); > +} > + > +static int ad8460_write_raw(struct iio_dev *indio_dev, > + struct iio_chan_spec const *chan, > + int val, > + int val2, > + long mask) > +{ > + struct ad8460_state *state =3D iio_priv(indio_dev); > + > + switch (mask) { > + case IIO_CHAN_INFO_RAW: > + iio_device_claim_direct_scoped(return -EBUSY, indio_dev) > + return ad8460_set_sample(state, val); > + unreachable(); > + default: > + return -EINVAL; > + } > +} > +static int ad8460_probe(struct spi_device *spi) > +{ > + struct ad8460_state *state; > + struct iio_dev *indio_dev; > + struct regulator *vrefio; > + int ret; > + > + indio_dev =3D devm_iio_device_alloc(&spi->dev, sizeof(*state)); > + if (!indio_dev) > + return -ENOMEM; > + > + state =3D iio_priv(indio_dev); > + mutex_init(&state->lock); > + > + state->spi =3D spi; > + > + state->regmap =3D devm_regmap_init_spi(spi, &ad8460_regmap_config); > + if (IS_ERR(state->regmap)) > + return dev_err_probe(&spi->dev, PTR_ERR(state->regmap), > + "Failed to initialize regmap"); > + > + ret =3D devm_iio_dmaengine_buffer_setup_ext(&spi->dev, indio_dev, "tx", > + IIO_BUFFER_DIRECTION_OUT); Ah. I take back my binding comment. I assume this is mapping some non stand= ard interface for the parallel data flow? > + if (ret) > + return dev_err_probe(&spi->dev, ret, > + "Failed to get DMA buffer\n"); > + > + state->sync_clk =3D devm_clk_get_enabled(&spi->dev, "sync_clk"); > + if (IS_ERR(state->sync_clk)) > + return dev_err_probe(&spi->dev, PTR_ERR(state->sync_clk), > + "Failed to get sync clk\n"); > + > + vrefio =3D devm_regulator_get_optional(&spi->dev, "vrefio"); > + if (IS_ERR(vrefio)) { > + if (PTR_ERR(vrefio) !=3D -ENODEV) > + return dev_err_probe(&spi->dev, PTR_ERR(vrefio), > + "Failed to get vref regulator\n"); > + > + state->vref_mv =3D 1200; > + > + } else { > + ret =3D regulator_enable(vrefio); > + if (ret) > + return dev_err_probe(&spi->dev, ret, > + "Failed to enable vrefio regulator\n"); > + > + ret =3D devm_add_action_or_reset(&spi->dev, > + ad8460_regulator_disable, > + vrefio); > + if (ret) > + return ret; > + > + ret =3D regulator_get_voltage(vrefio); > + if (ret < 0) > + return dev_err_probe(&spi->dev, ret, > + "Failed to get ref voltage\n"); > + > + if (!in_range(ret, AD8460_MIN_VREFIO_UV, AD8460_MAX_VREFIO_UV)) > + return dev_err_probe(&spi->dev, -EINVAL, > + "Invalid ref voltage range(%u) [%u, %u]\n", > + ret, AD8460_MIN_VREFIO_UV, > + AD8460_MAX_VREFIO_UV); > + > + state->vref_mv =3D ret / 1000; > + } > + > + ret =3D device_property_read_u32(&spi->dev, "adi,rset-ohms", > + &state->rset_ohms); > + if (!ret) { > + if (!in_range(state->rset_ohms, AD8460_MIN_RSET_OHMS, > + AD8460_MAX_RSET_OHMS)) > + return dev_err_probe(&spi->dev, -EINVAL, > + "Invalid resistor set range(%u) [%u, %u]\n", > + state->rset_ohms, > + AD8460_MIN_RSET_OHMS, > + AD8460_MAX_RSET_OHMS); > + } > + > + ret =3D ad8460_reset(state); > + if (ret) > + return ret; > + > + /* Enables DAC by default */ > + ret =3D regmap_update_bits(state->regmap, AD8460_CTRL_REG(0x01), > + AD8460_HVDAC_SLEEP_MSK, > + FIELD_PREP(AD8460_HVDAC_SLEEP_MSK, 0)); > + if (ret) > + return ret; > + > + indio_dev->name =3D "ad8460"; > + indio_dev->info =3D &ad8460_info; > + indio_dev->channels =3D ad8460_channels; > + indio_dev->num_channels =3D ARRAY_SIZE(ad8460_channels); > + indio_dev->modes =3D INDIO_DIRECT_MODE | INDIO_BUFFER_HARDWARE; > + indio_dev->setup_ops =3D &ad8460_buffer_setup_ops; > + > + ret =3D devm_iio_device_register(&spi->dev, indio_dev); > + if (ret) > + return ret; > + > + ad8460_debugfs_init(indio_dev); > + > + return 0; > +} > + > +static const struct of_device_id ad8460_of_match[] =3D { > + { .compatible =3D "adi, ad8460" }, > + { }, No comma on 'null' terminators like this as we don't want to let people put anything after them. > +}; > +MODULE_DEVICE_TABLE(of, ad8460_of_match);