From nobody Tue Dec 16 14:39:06 2025 Received: from mx0b-00128a01.pphosted.com (mx0a-00128a01.pphosted.com [148.163.135.77]) (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 D2B1422577C; Thu, 8 May 2025 12:32:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.163.135.77 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1746707564; cv=none; b=o3LrtnyaZfzDMethSLJqq/teLsekH6SmONoe+ClI/mR1aeGX+PRJKfZxj1kY6bynGmr0QzPbFtEz7f3kEadKB1G/Z1D8Fj0J8OJMY/gJ06jjAd/PTNtyvvNqvytFYhzsNZvgaEvxm6wFm8tCZIvZiY9eQ9whETg21/ZTYHuVByI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1746707564; c=relaxed/simple; bh=Jwpu6YdHH3kNDY9JO80FOOQiXWmBMRZum5SYHEwWhVY=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=DA5tVrUTES/uH4kPfUzqKMbQVtXlrnRt00mwlDwLtMYpnTX3QU0wSD4Cw+QhL8VCb04m4d2tZRee7nmdNSEVhcss/mC355lKs+9/jXUrLZZykUg0Px81DKYb42J640hVrc/3U21zEV3uy9Ml7pyWk4f43DFizU72x1itoCocS88= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=analog.com; spf=pass smtp.mailfrom=analog.com; dkim=pass (2048-bit key) header.d=analog.com header.i=@analog.com header.b=qWLNNLQL; arc=none smtp.client-ip=148.163.135.77 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=analog.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=analog.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=analog.com header.i=@analog.com header.b="qWLNNLQL" Received: from pps.filterd (m0375855.ppops.net [127.0.0.1]) by mx0b-00128a01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 548BDZAP010473; Thu, 8 May 2025 08:32:20 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=analog.com; h= content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=DKIM; bh=7dkvz t5EByozw81MJjeobuPYPumFgB5VvJsZNm22UaE=; b=qWLNNLQL+FLIpqSn1VBtX tbGLl+3U/4wbHwuuRtZTDjlU0s4dKCSMRk+f/bBxHwgHTiFXJ08MJ5nG1/2+U68P ATXur7DEnjTkriSPRdGNo5Tgv4NHBU11+/EJAkcDv4GqGafGe9rfX3HGAVc2Ys0d GIRszSpTVwAYkS5ea6BWfZFXnTFGHLDKlgFx1uwXD1tOvJR/1/86O84mMI/5ku0c ldfQsGS+yX1TcDayM7D9TUQ1CN5naUPgZfA0XFqNWBUuNQ7oQJHnnGFxB94lfgGT wk9Rlns5//CoD14/wy2E3h4Kdp2gx42ri12Myk6166bg8WHzj26Hr0S8iOJ8nO/c Q== Received: from nwd2mta4.analog.com ([137.71.173.58]) by mx0b-00128a01.pphosted.com (PPS) with ESMTPS id 46gr04scxq-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 08 May 2025 08:32:19 -0400 (EDT) Received: from ASHBMBX8.ad.analog.com (ASHBMBX8.ad.analog.com [10.64.17.5]) by nwd2mta4.analog.com (8.14.7/8.14.7) with ESMTP id 548CWIEi006307 (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Thu, 8 May 2025 08:32:18 -0400 Received: from ASHBCASHYB5.ad.analog.com (10.64.17.133) by ASHBMBX8.ad.analog.com (10.64.17.5) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.14; Thu, 8 May 2025 08:32:18 -0400 Received: from ASHBMBX8.ad.analog.com (10.64.17.5) by ASHBCASHYB5.ad.analog.com (10.64.17.133) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.14; Thu, 8 May 2025 08:32:18 -0400 Received: from zeus.spd.analog.com (10.66.68.11) by ashbmbx8.ad.analog.com (10.64.17.5) with Microsoft SMTP Server id 15.2.986.14 via Frontend Transport; Thu, 8 May 2025 08:32:18 -0400 Received: from romlx5.adlk.analog.com ([10.48.65.73]) by zeus.spd.analog.com (8.15.1/8.15.1) with ESMTP id 548CVFtg002317; Thu, 8 May 2025 08:32:09 -0400 From: Pop Ioan Daniel To: Lars-Peter Clausen , Michael Hennerich , Jonathan Cameron , "David Lechner" , =?UTF-8?q?Nuno=20S=C3=A1?= , Andy Shevchenko , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Sergiu Cuciurean , "Dragos Bogdan" , Antoniu Miclaus , Olivier Moysan , Javier Carrasco , Matti Vaittinen , Tobias Sperling , Alisa-Dariana Roman , Marcelo Schmitt , Matteo Martelli , Ioan Daniel , , , Subject: [PATCH v2 4/4] iio: adc: ad7405: add ad7405 driver Date: Thu, 8 May 2025 15:30:57 +0300 Message-ID: <20250508123107.3797042-5-pop.ioan-daniel@analog.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250508123107.3797042-1-pop.ioan-daniel@analog.com> References: <20250508123107.3797042-1-pop.ioan-daniel@analog.com> 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 X-ADIRuleOP-NewSCL: Rule Triggered X-Proofpoint-Spam-Details-Enc: AW1haW4tMjUwNTA4MDEwMiBTYWx0ZWRfX+KzPkRwzC7e9 Eb2pGr5YsoZ3yT2pxbOMdkcx+qY2aTz2DGh9YHrjHn/eT/+K0JWfFWPAC3P6QBSlFHoN7ssbqLP W2G2U9luF+5YaliiVqrtZxGeQKAwL67EsQ7diEXN9vvK8j4MA7CMFORjytG8bk7P3e1ZQP9+ESo ucA3XNCy7A6WbMY1uvstY7hri9ZhLc04iy8jtRnL7K919+3g3QLLDzjU/Ihl+Y2MMsu3tAwD9Vl r5XoR/pPcRnR0u3EiGzHttAbr4r5+Z2q0LPRdB5MLdjXFqDH2F2J41NhiCE87DpDXaidIIAzHWk B4ws+JrMUKGmh1hm4qTXYcWRL3E/YZqxHX1DvbQlD9VTAO4y9BHaDxolDM+NtmyVsPDMWvdTsGC jiNNwC2hcg6m7yHChyCmPmgUYJSz/NTtUfKC5O2WBGE4gSBvyEIXC9O4rJ29nS3Wrmoy6U+O X-Authority-Analysis: v=2.4 cv=cfnSrmDM c=1 sm=1 tr=0 ts=681ca453 cx=c_pps a=3WNzaoukacrqR9RwcOSAdA==:117 a=3WNzaoukacrqR9RwcOSAdA==:17 a=IkcTkHD0fZMA:10 a=dt9VzEwgFbYA:10 a=gAnH3GRIAAAA:8 a=iGn3AVPVnOFhGmbdwOgA:9 a=3ZKOabzyN94A:10 a=QEXdDO2ut3YA:10 X-Proofpoint-GUID: W-AngUH9k6PGkA-w2rdmeVWsuLwtmvVP X-Proofpoint-ORIG-GUID: W-AngUH9k6PGkA-w2rdmeVWsuLwtmvVP X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1099,Hydra:6.0.736,FMLib:17.12.80.40 definitions=2025-05-08_04,2025-05-07_02,2025-02-21_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 bulkscore=0 suspectscore=0 phishscore=0 adultscore=0 mlxlogscore=999 lowpriorityscore=0 clxscore=1011 malwarescore=0 mlxscore=0 impostorscore=0 spamscore=0 classifier=spam authscore=0 authtc=n/a authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.19.0-2504070000 definitions=main-2505080102 Add support for the AD7405/ADUM770x, a high performance isolated ADC, 1-channel, 16-bit with a second-order =CE=A3-=CE=94 modulator that converts= an analog input signal into a high speed, single-bit data stream. Signed-off-by: Pop Ioan Daniel --- changes in v2: - sort the includes in alphabetical order - delete headers that aren't used - remove min_rate member - remove ad7405_update_scan_mode because there is only one channel - rename axi_clk_gen to clk - remove unuseful members from ad7405 state struct - return -EINVAL on ad7405_write_raw - fix indentation - remove blank lines - remove chan, bits, sign parameters from AD7405_IIO_CHANNEL - remove shift =3D 0 - add info_mask_shared_by_type with IIO_CHAN_INFO_SCALE and IIO_CHAN_INFO_OFFSET flags - add scan_index, differential, channel2 in AD7405_IIO_CHANNEL - remove ad7405_channel_masks[] - remove unuseful members from ad7405_chip_info struct - remove platform_get_drvdata() from probe - use device_get_match_data to be able to use different chip info - use devm_clk_get_enabled() for efficiency - add devm_add_action_or_reset to disable_unprepare the clock when the dri= ver is removed - replace the devm_regulator_bulk_get_enable before applying any other sig= nals - check for return value of 0 for st->ref_frequency - remove indio_dev->modes =3D INDIO_DIRECT_MODE - remove iio_backend_disable/enable that is done implicitly by devm_iio_backend_enable() drivers/iio/adc/Kconfig | 10 ++ drivers/iio/adc/Makefile | 1 + drivers/iio/adc/ad7405.c | 264 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 275 insertions(+) create mode 100644 drivers/iio/adc/ad7405.c diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index ad06cf556785..6ed1042636d9 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -251,6 +251,16 @@ config AD7380 To compile this driver as a module, choose M here: the module will be called ad7380. =20 +config AD7405 + tristate "Analog Device AD7405 ADC Driver" + select IIO_BACKEND + help + Say yes here to build support for Analog Devices AD7405, ADUM7701, + ADUM7702, ADUM7703 analog to digital converters (ADC). + + To compile this driver as a module, choose M here: the module will be + called ad7405. + config AD7476 tristate "Analog Devices AD7476 1-channel ADCs driver and other similar d= evices from AD and TI" depends on SPI diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index 07d4b832c42e..8115f30b7862 100644 --- a/drivers/iio/adc/Makefile +++ b/drivers/iio/adc/Makefile @@ -26,6 +26,7 @@ obj-$(CONFIG_AD7291) +=3D ad7291.o obj-$(CONFIG_AD7292) +=3D ad7292.o obj-$(CONFIG_AD7298) +=3D ad7298.o obj-$(CONFIG_AD7380) +=3D ad7380.o +obj-$(CONFIG_AD7405) +=3D ad7405.o obj-$(CONFIG_AD7476) +=3D ad7476.o obj-$(CONFIG_AD7606_IFACE_PARALLEL) +=3D ad7606_par.o obj-$(CONFIG_AD7606_IFACE_SPI) +=3D ad7606_spi.o diff --git a/drivers/iio/adc/ad7405.c b/drivers/iio/adc/ad7405.c new file mode 100644 index 000000000000..5fe36ce61819 --- /dev/null +++ b/drivers/iio/adc/ad7405.c @@ -0,0 +1,264 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Analog Devices AD7405 driver + * + * Copyright 2025 Analog Devices Inc. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +const unsigned int ad7405_dec_rates[] =3D { + 4096, 2048, 1024, 512, 256, 128, 64, 32, +}; + +struct ad7405_chip_info { + const char *name; + unsigned int max_rate; + struct iio_chan_spec channel[]; +}; + +struct ad7405_state { + struct iio_backend *back; + /* lock to protect multiple accesses to the device registers */ + struct mutex lock; + const struct ad7405_chip_info *info; + unsigned int sample_frequency_tbl[ARRAY_SIZE(ad7405_dec_rates)]; + unsigned int sample_frequency; + unsigned int ref_frequency; +}; + +static void ad7405_fill_samp_freq_table(struct ad7405_state *st) +{ + unsigned int i; + + for (i =3D 0; i < ARRAY_SIZE(ad7405_dec_rates); i++) + st->sample_frequency_tbl[i] =3D + DIV_ROUND_CLOSEST_ULL(st->ref_frequency, ad7405_dec_rates[i]); +} + +static int ad7405_set_sampling_rate(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + unsigned int samp_rate) +{ + struct ad7405_state *st =3D iio_priv(indio_dev); + unsigned int dec_rate, idx; + int ret; + + dec_rate =3D DIV_ROUND_CLOSEST_ULL(st->ref_frequency, samp_rate); + + idx =3D find_closest_descending(dec_rate, ad7405_dec_rates, + ARRAY_SIZE(ad7405_dec_rates)); + + dec_rate =3D ad7405_dec_rates[idx]; + + ret =3D iio_backend_oversampling_ratio_set(st->back, 0, dec_rate); + if (ret) + return ret; + + st->sample_frequency =3D DIV_ROUND_CLOSEST_ULL(st->ref_frequency, dec_rat= e); + + return 0; +} + +static int ad7405_read_raw(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, int *val, + int *val2, long info) +{ + struct ad7405_state *st =3D iio_priv(indio_dev); + + switch (info) { + case IIO_CHAN_INFO_SAMP_FREQ: + *val =3D st->sample_frequency; + return IIO_VAL_INT; + default: + return -EINVAL; + } +} + +static int ad7405_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int val, + int val2, long info) +{ + switch (info) { + case IIO_CHAN_INFO_SAMP_FREQ: + if (val < 1) + return -EINVAL; + return ad7405_set_sampling_rate(indio_dev, chan, val); + default: + return -EINVAL; + } +} + +static int ad7405_read_avail(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + const int **vals, int *type, int *length, + long info) +{ + struct ad7405_state *st =3D iio_priv(indio_dev); + + switch (info) { + case IIO_CHAN_INFO_SAMP_FREQ: + *vals =3D st->sample_frequency_tbl; + *length =3D ARRAY_SIZE(st->sample_frequency_tbl); + *type =3D IIO_VAL_INT; + return IIO_AVAIL_LIST; + default: + return -EINVAL; + } +} + +static void ad7405_clk_disable_unprepare(void *clk) +{ + clk_disable_unprepare(clk); +} + +static const struct iio_info ad7405_iio_info =3D { + .read_raw =3D &ad7405_read_raw, + .write_raw =3D &ad7405_write_raw, + .read_avail =3D &ad7405_read_avail, +}; + +#define AD7405_IIO_CHANNEL { \ + .type =3D IIO_VOLTAGE, \ + .info_mask_shared_by_all =3D BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .info_mask_shared_by_all_available =3D BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .info_mask_shared_by_type =3D BIT(IIO_CHAN_INFO_SCALE) | \ + BIT(IIO_CHAN_INFO_OFFSET), \ + .indexed =3D 1, \ + .channel =3D 0, \ + .channel2 =3D 1, \ + .differential =3D 1, \ + .scan_index =3D 0, \ + .scan_type =3D { \ + .sign =3D 'u', \ + .realbits =3D 16, \ + .storagebits =3D 16, \ + }, \ +} + +static const struct ad7405_chip_info ad7405_chip_info =3D { + .name =3D "AD7405", + .channel =3D { + AD7405_IIO_CHANNEL, + }, +}; + +static const struct ad7405_chip_info adum7701_chip_info =3D { + .name =3D "ADUM7701", + .channel =3D { + AD7405_IIO_CHANNEL, + }, +}; + +static const char * const ad7405_power_supplies[] =3D { + "vdd1", "vdd2", +}; + +static int ad7405_probe(struct platform_device *pdev) +{ + const struct ad7405_chip_info *chip_info; + struct device *dev =3D &pdev->dev; + struct iio_dev *indio_dev; + struct ad7405_state *st; + struct clk *clk; + int ret; + + indio_dev =3D devm_iio_device_alloc(dev, sizeof(*st)); + if (!indio_dev) + return -ENOMEM; + + st =3D iio_priv(indio_dev); + + ret =3D devm_mutex_init(dev, &st->lock); + if (ret) + return ret; + + chip_info =3D device_get_match_data(dev); + if (!chip_info) + return dev_err_probe(dev, -EINVAL, "no chip info\n"); + + ret =3D devm_regulator_bulk_get_enable(dev, ARRAY_SIZE(ad7405_power_suppl= ies), + ad7405_power_supplies); + + if (ret) + return dev_err_probe(dev, ret, "failed to get and enable supplies"); + + clk =3D devm_clk_get_enabled(dev, NULL); + if (IS_ERR(clk)) + return PTR_ERR(clk); + + ret =3D devm_add_action_or_reset(dev, ad7405_clk_disable_unprepare, clk); + if (ret) + return ret; + + st->ref_frequency =3D clk_get_rate(clk); + if (!(st->ref_frequency)) + return -EINVAL; + + ad7405_fill_samp_freq_table(st); + + indio_dev->dev.parent =3D dev; + indio_dev->name =3D chip_info->name; + indio_dev->channels =3D chip_info->channel; + indio_dev->num_channels =3D 1; + indio_dev->info =3D &ad7405_iio_info; + + st->back =3D devm_iio_backend_get(dev, NULL); + if (IS_ERR(st->back)) + return dev_err_probe(dev, PTR_ERR(st->back), + "failed to get IIO backend"); + + ret =3D iio_backend_chan_enable(st->back, 0); + if (ret) + return ret; + + ret =3D devm_iio_backend_request_buffer(dev, st->back, indio_dev); + if (ret) + return ret; + + ret =3D devm_iio_backend_enable(dev, st->back); + if (ret) + return ret; + + ret =3D ad7405_set_sampling_rate(indio_dev, &indio_dev->channels[0], + chip_info->max_rate); + if (ret) + return ret; + + return devm_iio_device_register(dev, indio_dev); +} + +/* Match table for of_platform binding */ +static const struct of_device_id ad7405_of_match[] =3D { + { .compatible =3D "adi,ad7405", .data =3D &ad7405_chip_info, }, + { .compatible =3D "adi,adum7701", .data =3D &adum7701_chip_info, }, + { .compatible =3D "adi,adum7702", .data =3D &adum7701_chip_info, }, + { .compatible =3D "adi,adum7703", .data =3D &adum7701_chip_info, }, + { /* end of list */ }, +}; +MODULE_DEVICE_TABLE(of, ad7405_of_match); + +static struct platform_driver ad7405_driver =3D { + .driver =3D { + .name =3D "ad7405", + .owner =3D THIS_MODULE, + .of_match_table =3D ad7405_of_match, + }, + .probe =3D ad7405_probe, +}; +module_platform_driver(ad7405_driver); + +MODULE_AUTHOR("Dragos Bogdan "); +MODULE_AUTHOR("Pop Ioan Daniel "); +MODULE_DESCRIPTION("Analog Devices AD7405 driver"); +MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS("IIO_BACKEND"); --=20 2.34.1