From nobody Tue Sep 29 11:58:32 2026 Received: from mail-ot1-f43.google.com (mail-ot1-f43.google.com [209.85.210.43]) (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 0445721256C for ; Sat, 8 Aug 2026 00:20:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.43 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786148438; cv=none; b=JTgpLAqvXWxWbr17y2BNgfviwo0zNA14lWOUtXjfBmGZBBbz/GksKlcMgcRo7iPv2DrgG+RLapJP+eb1gygT1QhsUOfnIMyOqOvTzOcidW1e4Es8TSzZ/PDUDfgGDkzquwbn/YCh24Z8BV1m5/XobJWK91+9VkyHX/DyaX6jEig= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786148438; c=relaxed/simple; bh=qGiSqDTEB8IueyZdnsJoTvnzBrP8bhh2S9mqNS/Cs8w=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Aiscg1NOUVy4U7JoxGFa+sDUNnRhPX03EX5epB/uBlZEsUUhMo5qq4eJeM9NgNFE5W3AwnChtKcdO50mDm8JHk0K36AdT5rsREZGT/2nLWJafqVmJD1/R6J5axCHoEYVMx8WKaz54xoYNrnTnuqhTCNFwQOfFPcppFIfVMiTgMA= 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 header.i=@baylibre.com header.b=ZEiTrGD2; arc=none smtp.client-ip=209.85.210.43 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 header.i=@baylibre.com header.b="ZEiTrGD2" Received: by mail-ot1-f43.google.com with SMTP id 46e09a7af769-7e9ef94c0e2so84327a34.3 for ; Fri, 07 Aug 2026 17:20:35 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre.com; s=google; t=1786148435; x=1786753235; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=H+3eFTdZbxSJ8d10PJQLTyMN38nlrE1qFgcsHMvaT9c=; b=ZEiTrGD2/lpfyql5mQHAsOHpifzZAI78vkaHG7fjyd03JJQY5MSfpRrMdpQV5fCahs 56NdTjDjY4ZyhnOUGfHWoI+x50CeMhhG9fRst9vEkeFGgUWEzGAZISEY0WKloSYg2RFV q+EYq1Pkq2+nkIluiSAOTHCNspEUBaY9nf3WGQSsX+9sk3vvh+6zj0/os6CAAqdc4vGZ Gr7FsfS8tac57rJLHbPvA16Bdl04CyO/pA9LuENvTGdjcnG+xg52HwdUuT8+2GeJSsEB AdCEftJ7w3CmXuzqD5rUPnRJi0WeVDImMNg9S82rTgakJDjaNS/q6TNNaUmAjGJdfrH3 kMXQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1786148435; x=1786753235; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=H+3eFTdZbxSJ8d10PJQLTyMN38nlrE1qFgcsHMvaT9c=; b=YYvzkaHncrp8Q4yLlkGv744gXmzY/xMsuhQQgs1D0KFgre3+s/9nGqJI8zFT2/uGtS /iRQqpAp8Qcpj25063hVOtXCq4NgclEpB7w2S8HTZXNa9UdRl7pPoMYb4a6nbNZUF6Xz E3UhWmFnjgdYSDFt4cuL1kxw+ESICp+M8Jqgsv8DFNkNkDgu4pOh9TWFLnVuRRFOCGQ4 ap483yt1A7wKdbbnyNBBULRi0VCIMGaG6WbrGeHRbSGFiRtSO4ete7oG0Nks2cYspqAG bDHjMMAhOves0ys+DkBP7KcE9bpDxDImr38tyjhecTPDM6Z4/9AmW7UIqJG4q6NQF44P WEfw== X-Forwarded-Encrypted: i=1; AHgh+RpBWyOUcFwe2Yr1yJDsy/4u4aEUBsnu5TkZjLaQzhKAoXSbSCGb3vkPvQY1KwFuCrEjE3lHW+0JiZ0co14=@vger.kernel.org X-Gm-Message-State: AOJu0YydxsjCKhAl2DOVIcNU2O6lo7LYuL3PrH+VdLPhoz0vVRgUvyWK 4w3I3xXn4LO46FZf1wQNHDzcoEYsIvs9zSS9C5mMoakvby5wsgNWyurxyXS7fuUpgIg= X-Gm-Gg: AR+sD11mUGm8fLcIr4PX1IC662UOeN4uHDCctXxyIyufsXNlPjfwdPGfx35s2RxWwqk M6evS3x7edZ1i5LHp0yqQjO18EaGqAgshuo73VsAv/jddTdG5354xlYZ9HLWbaacRXUuAuqfgta TK/EXyxQ0U1gZJkCQvAPdnXSVWAUInEtKGGwIJx6UQ7CnCn2AdUvngPx0S8FLpjV/5fTeaxbdAs iqJX6vVeZ2zl0QRAfulZ5KB6u5sIEt04Wz/BftHcJymR+OszPloaFpU/U8Nyh7K6vY8WW0ZlZjd r007z/ziw4H2UPeCDbdu3Ak7kvcCT1aR9VcszyWQErRynJ3lpew5orjjdM7P0yOKiXjv9Pjoh5E y72ewiBatiXnsK2yuWxpTjKe9KuijyQXBTp4DjxJwFYfBEWdZUxJecIfvTD342BYBqrUsJrZHNq ujnd4AaZOPthq9N9i3chscIqZPhPyzDRE0h2wPyyaKfbo0CpU4+YBpwJosiKzTdqM0jw== X-Received: by 2002:a05:6830:2302:b0:7e6:de36:3f35 with SMTP id 46e09a7af769-7f34ded541dmr8869416a34.10.1786148434873; Fri, 07 Aug 2026 17:20:34 -0700 (PDT) Received: from [127.0.1.1] ([2600:8803:e7e4:500:b714:88c:313d:dee2]) by smtp.gmail.com with ESMTPSA id 46e09a7af769-7f35b5a7616sm2526147a34.8.2026.08.07.17.20.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 07 Aug 2026 17:20:33 -0700 (PDT) From: "David Lechner (TI)" Date: Fri, 07 Aug 2026 19:19:46 -0500 Subject: [PATCH 1/5] iio: adc: ti-ads112c14: support external clock 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: <20260807-iio-adc-ti-ads112c14-filter-support-v1-1-4d3ba00caf18@baylibre.com> References: <20260807-iio-adc-ti-ads112c14-filter-support-v1-0-4d3ba00caf18@baylibre.com> In-Reply-To: <20260807-iio-adc-ti-ads112c14-filter-support-v1-0-4d3ba00caf18@baylibre.com> To: Jonathan Cameron , =?utf-8?q?Nuno_S=C3=A1?= , Andy Shevchenko Cc: linux-iio@vger.kernel.org, linux-kernel@vger.kernel.org, "David Lechner (TI)" X-Mailer: b4 0.17-dev X-Developer-Signature: v=1; a=openpgp-sha256; l=3113; i=dlechner@baylibre.com; h=from:subject:message-id; bh=qGiSqDTEB8IueyZdnsJoTvnzBrP8bhh2S9mqNS/Cs8w=; b=owEBbQGS/pANAwAKAcLMIAH/AY/AAcsmYgBqdnYvkokHIEA5xvJYAQO9hcrbwLzgKLWjBL2dt zF4xVdHKGWJATMEAAEKAB0WIQTsGNmeYg6D1pzYaJjCzCAB/wGPwAUCanZ2LwAKCRDCzCAB/wGP wGA5CACBkeabgpw1sbNcQ/SZpsdApWZh5P7awA65AZQyBZfdkDErytOXODpo+m2twrZTHvTja1Y gawWUrYszm2qEnYBWLFwWI3dZ7cq5IfoCejEROzN8JBNOf/Y259+WV3XayJB34OeX1FMke5rppj enK0CRXUiIWBvdlaryCCC+Nl2fhmG+D1pNBVINtFSh47Fjq+4NXKmjV1iOymYKnIyM6NXVKfqb0 WOy/20JfJ2I55qg5vCvEvw/MSxWnuunoOOoHX3VMM1TixW2I/6CjtcL2INOxXkwwAOBWUJPIUPI +i1Py3LfrrJ3bpoOMZcy+wYaA4ELXWi5vj9m8Nmu1ZsyEtdq X-Developer-Key: i=dlechner@baylibre.com; a=openpgp; fpr=8A73D82A6A1F509907F373881F8AF88C82F77C03 Add support for external an external clock source to the TI ADS112C14 ADC driver. The unused fclk_hZ field is added in preparation for filter support. Signed-off-by: David Lechner (TI) --- drivers/iio/adc/ti-ads112c14.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/drivers/iio/adc/ti-ads112c14.c b/drivers/iio/adc/ti-ads112c14.c index fa6eeaf81738..5f03e6985efa 100644 --- a/drivers/iio/adc/ti-ads112c14.c +++ b/drivers/iio/adc/ti-ads112c14.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -178,6 +179,8 @@ static const u32 ads112c14_pga_gains_x10[] =3D { 200, 320, 500, 640, 1000, 1280, 2000, 2560, /* 8 - 15 */ }; =20 +#define ADS112C14_INTERNAL_CLK_Hz 4096000 + #define ADS112C14_I2C_CRC8_POLYNOMIAL 0x07 DECLARE_CRC8_TABLE(ads112c14_crc8_table); =20 @@ -268,6 +271,7 @@ struct ads112c14_data { struct iio_trigger *drdy_trig; /* Synchronizes access to register value fields. */ struct mutex lock; + long fclk_Hz; int drdy_irq; struct completion drdy_completion; bool i2c_crc_enabled; @@ -1516,6 +1520,7 @@ static int ads112c14_probe(struct i2c_client *client) const struct ads112c14_chip_info *info; struct iio_dev *indio_dev; struct ads112c14_data *data; + struct clk *clk; bool need_avdd_ref, need_ext_ref; u32 refp_uV =3D 0; u32 refn_uV =3D 0; @@ -1608,6 +1613,12 @@ static int ads112c14_probe(struct i2c_client *client) return dev_err_probe(dev, -EINVAL, "external reference measurements require either refp-supply or ti= ,refp-refn-resistor-ohms property\n"); =20 + clk =3D devm_clk_get_optional_enabled(dev, NULL); + if (IS_ERR(clk)) + return dev_err_probe(dev, PTR_ERR(clk), "failed to get clk\n"); + + data->fclk_Hz =3D clk ? clk_get_rate(clk) : ADS112C14_INTERNAL_CLK_Hz; + /* It takes some time for the internal reference to stabilize. */ fsleep(10 * USEC_PER_MSEC); =20 @@ -1678,6 +1689,10 @@ static int ads112c14_probe(struct i2c_client *client) return dev_err_probe(dev, data->drdy_irq, "failed to get drdy interrupt\n"); =20 + if (clk) + return dev_err_probe(dev, -EINVAL, + "cannot use both DRDY and CLK - they share the same pin\n"); + /* * REVISIT: would probably need to implement a pin controller in * order to support open drain option here. @@ -1717,6 +1732,20 @@ static int ads112c14_probe(struct i2c_client *client) return ret; } =20 + if (clk) { + ret =3D regmap_update_bits(data->regmap, ADS112C14_REG_GPIO_CFG, + ADS112C14_GPIO_CFG_GPIO3_CFG, + FIELD_PREP(ADS112C14_GPIO_CFG_GPIO3_CFG, + ADS112C14_GPIO_CFG_GPIO_CFG_INPUT)); + if (ret) + return ret; + + ret =3D regmap_set_bits(data->regmap, ADS112C14_REG_DEVICE_CFG, + ADS112C14_DEVICE_CFG_CLK_SEL); + if (ret) + return ret; + } + ads112c14_populate_tables(data); =20 indio_dev->name =3D info->name; --=20 2.43.0 From nobody Tue Sep 29 11:58:32 2026 Received: from mail-ot1-f52.google.com (mail-ot1-f52.google.com [209.85.210.52]) (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 1524122CBE6 for ; Sat, 8 Aug 2026 00:20:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.52 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786148442; cv=none; b=aJlFENW0X+xGvB3xq3PfxwlGlqngUDcLPojURplL51YMaxcZOEvVxzVoaZ33gkcQx8zPy2vfZWQcC1rn0lH3YP2GDkvTJKUXb5iGCjnAKsLk6QBAD7+jMH0Nh71mZuefOARImc3av1uyd3T9a7xLAPkO51lDRoyWELNoFCN4T0w= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786148442; c=relaxed/simple; bh=154u7Jk2wf7g0zhyit0KoGAZL+ie3TlzVOfJ6SBf8Kc=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=IucTn6VeXZJI/uH85X77u9ZsVnUaW9UmKWS3qbElodaGBnDh5R5+RT0pzDk009V8NYGhI1sO1YzLbshm6CBuxErYhizcYVPKXb50C0KcGZtE2fUH6rF1dZSEOsti1SUG39XV2AJcXxNpTdfcJDFdXrYN4uRhKj6kCUM/3hlsq+4= 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 header.i=@baylibre.com header.b=ITSL1Rix; arc=none smtp.client-ip=209.85.210.52 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 header.i=@baylibre.com header.b="ITSL1Rix" Received: by mail-ot1-f52.google.com with SMTP id 46e09a7af769-7eb9b427da2so1497292a34.0 for ; Fri, 07 Aug 2026 17:20:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre.com; s=google; t=1786148436; x=1786753236; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=lPAkkK7lnRiQLocAijMmBt97fxjS7WIGdRN9v95Ll4E=; b=ITSL1RixLsrCzrcU8nGTu/0NybVu8mCrljZnj8ibMTCTBPrt/w0nt9qjMiOGyFMzeL 7zKvM8XYDpq3pS7n/wOV11qERX1Igkz8C+EeQx1FN/aa2s/yeF7fS9gXcHQTgQ/2lf5J PzQp6GqFMttbnXUD+laZp8OzTxY1tw8lKqeZ8Rk+srC1J/SUF2udapJxS/gPOHiay7cA yOSKrTPusM9nSV+OgBKZO8d7AyBYWmNd09gFLOqgiOecMq8w/eZ1YrBqZ3s1JG7R12GE MuLpp0OSeGQBZjdvhBGhkFcsQoPo9xFKaglUaWtY5isV2modWyS5c+3/JpU/WGbkZWl2 I9Ug== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1786148436; x=1786753236; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=lPAkkK7lnRiQLocAijMmBt97fxjS7WIGdRN9v95Ll4E=; b=KDHE3q/NRlmGBHnVJIGgU1OMOXO0u1NHN7SPo/bI3lQQdYPdOlP9729wnbB1zaKSvk MRgKanvJtcF2Vd7H7/6JeCH4r9hXpK2HsVslwZKek9h14ykCmNbijgLMGCXUxiZIYK+P JQTr5eQ1ro6U2PLaNQLplfi4qEQN4DMk4/OSCLgH7CfTBP4kfmeNTXOIc472YaIqW5fp cw/t/tzjm4xGrGstEL/A0HoVeK9wJ0IhXMmShCSR2H0ELeefjsI8ulyCYj9uMAugnJo6 fZ3aV+8i0eEnq5Tq3yHq5eaLnvWDW2mLxI+BpyI9xzQrXOT7OB/qC9ocL1VqwMANOCs4 olPw== X-Forwarded-Encrypted: i=1; AHgh+Rrl+h3DAKJlgB4f6qhlaWftl5h7KTFaUYqNNz8Na/et/wSLj45Jv11qdP/mq7K9zJEESphw3dnN4IRdYLY=@vger.kernel.org X-Gm-Message-State: AOJu0YydFaoVkbcssjeWfLdBgPC4Qh576e0S7ZPr0AVI2RiUeDRCsJW3 JbVo6hYFSmD7xMYQcAWhi6hyi2fiwrGo9C4MkQPgRh8xDdbr+V71Tx9oCPKpRpUDFaKEFZsXKXO EpfZARq0= X-Gm-Gg: AR+sD13GT3fTp2Uw7JDiCHb6ge4JVncYQvIaym94SeGmfnAEB29/P0U3egd5SDhvh4/ P8URdJPHdlb+NmVho1OZtxlcQG/CIwEQooqB/D5zU7Ej6qZ6syoGWhQMGHR/oABvbzBAd4Z2udV dUpcFII4AvGXPg++Coalded+RVcPiyXTBVgZd0W4ihFAl+cf0/+2EJKLYAZhCkSLGrvikBh8Z/j 8Q1oFhdZsIPPYr9W2heFV5plu+fdDu/dO4KualOGJrnF/Ozv2Dwld+knH53WvGJjICuMYeAK4z4 T+ygmeY5ErUCZ4st5JjEgb329hNPTgcysG9Ckz8qgAZpADDfPM4fCyeTu5G3lt71Ek3cer28Y2A dGQTBgsFEnsXfhtPe8KE6nG8aEGk31twX9qK/aC1V4+nnu+Kt2YD+a7ZTxoZkVSpV6hxr6goq9N 5Nk3WHiYjZ7HSq3QYDNV+gWGTy+SHOZgMEX1mNSb/P7FRL21nQ0Y1t+bZTZjoGGk1g X-Received: by 2002:a05:6820:811b:b0:6ae:aa9b:b8f1 with SMTP id 006d021491bc7-6b045000e95mr1433320eaf.10.1786148435822; Fri, 07 Aug 2026 17:20:35 -0700 (PDT) Received: from [127.0.1.1] ([2600:8803:e7e4:500:b714:88c:313d:dee2]) by smtp.gmail.com with ESMTPSA id 46e09a7af769-7f35b5a7616sm2526147a34.8.2026.08.07.17.20.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 07 Aug 2026 17:20:35 -0700 (PDT) From: "David Lechner (TI)" Date: Fri, 07 Aug 2026 19:19:47 -0500 Subject: [PATCH 2/5] iio: adc: ti-ads112c14: add filter support 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: <20260807-iio-adc-ti-ads112c14-filter-support-v1-2-4d3ba00caf18@baylibre.com> References: <20260807-iio-adc-ti-ads112c14-filter-support-v1-0-4d3ba00caf18@baylibre.com> In-Reply-To: <20260807-iio-adc-ti-ads112c14-filter-support-v1-0-4d3ba00caf18@baylibre.com> To: Jonathan Cameron , =?utf-8?q?Nuno_S=C3=A1?= , Andy Shevchenko Cc: linux-iio@vger.kernel.org, linux-kernel@vger.kernel.org, "David Lechner (TI)" X-Mailer: b4 0.17-dev X-Developer-Signature: v=1; a=openpgp-sha256; l=26790; i=dlechner@baylibre.com; h=from:subject:message-id; bh=154u7Jk2wf7g0zhyit0KoGAZL+ie3TlzVOfJ6SBf8Kc=; b=owEBbQGS/pANAwAKAcLMIAH/AY/AAcsmYgBqdnY2Fv53h/nqHt/7Sm5RECB+Z6I/2lAMD2xLg 1z9h7I8BHWJATMEAAEKAB0WIQTsGNmeYg6D1pzYaJjCzCAB/wGPwAUCanZ2NgAKCRDCzCAB/wGP wAIcCACayUfQL5XkSHt/8JRrttppNgw7jR6lQPUEo6mN+jLq2kegSPULnvP450EfkwxP66ONTRr SDq0U4+R0XN8prDB+GHgdVD007W2Fjl93gAiYTYcdmx7yj+ayqBVexA7RJ7/XzMWRq45iEpY+m+ 4l1Dj7pb3CuurMnF+1TJ02ZkiJvaF930uZ6Xic8ZohBZA/6k8Tgs05/ZxVc0gbEuk6Fy6JPBdtZ mqhTA+N6YgSl7OovrDkfIarOsaT08o7ynGk2mLFq5lQ0sCHwKou5Ew3vjb/xeVZh+FjnposD6JS vg6PhFEvnbH3VpzonM2eNahAiw3HwP/QI+C96jA8MSZvessc X-Developer-Key: i=dlechner@baylibre.com; a=openpgp; fpr=8A73D82A6A1F509907F373881F8AF88C82F77C03 Add support for filter_type, oversampling_ratio and sampling_frequency attributes to the ti-ads112c14 driver. On these chips, these three controls are interdependent and the SPEED_MODE register value has a different meaning depending on the filter type, which makes the interactions a bit complex. As such, the expectation is that the user will set the filter type first, then depending on the filter type, either set the oversampling ratio or the sampling frequency and finally the other of these two. Signed-off-by: David Lechner (TI) --- Note: I intend to sumbit a documentation patch later that explains the "right way" to set these three attributes since it is a bit odd due to the conditional interdependencies. --- drivers/iio/adc/ti-ads112c14.c | 493 +++++++++++++++++++++++++++++++++++++= ++-- 1 file changed, 480 insertions(+), 13 deletions(-) diff --git a/drivers/iio/adc/ti-ads112c14.c b/drivers/iio/adc/ti-ads112c14.c index 5f03e6985efa..a73c0d6f0f65 100644 --- a/drivers/iio/adc/ti-ads112c14.c +++ b/drivers/iio/adc/ti-ads112c14.c @@ -92,6 +92,14 @@ #define ADS112C14_DATA_RATE_CFG_DELAY GENMASK(7, 4) #define ADS112C14_DATA_RATE_CFG_GC_EN BIT(3) #define ADS112C14_DATA_RATE_CFG_FLTR_OSR GENMASK(2, 0) +#define ADS112C14_DATA_RATE_CFG_FLTR_OSR_16 0 +#define ADS112C14_DATA_RATE_CFG_FLTR_OSR_32 1 +#define ADS112C14_DATA_RATE_CFG_FLTR_OSR_128 2 +#define ADS112C14_DATA_RATE_CFG_FLTR_OSR_256 3 +#define ADS112C14_DATA_RATE_CFG_FLTR_OSR_512 4 +#define ADS112C14_DATA_RATE_CFG_FLTR_OSR_1024 5 +#define ADS112C14_DATA_RATE_CFG_FLTR_OSR_25SPS 6 +#define ADS112C14_DATA_RATE_CFG_FLTR_OSR_20SPS 7 =20 #define ADS112C14_REG_MUX_CFG 0x07 #define ADS112C14_MUX_CFG_AINP GENMASK(7, 4) @@ -181,6 +189,43 @@ static const u32 ads112c14_pga_gains_x10[] =3D { =20 #define ADS112C14_INTERNAL_CLK_Hz 4096000 =20 +/* Index corresponds to first 2 ADS112C14_DATA_RATE_CFG_FLTR_OSR values. */ +static const int ads112c14_sinc4_osr_available[] =3D { + 16, 32 +}; + +/* Index corresponds to next 4 ADS112C14_DATA_RATE_CFG_FLTR_OSR values. */ +static const int ads112c14_sinc4_sinc1_osr_available[] =3D { + 128, 256, 512, 1024 +}; + +/* Index corresponds to ADS112C14_DEVICE_CFG_SPEED_MODE value. */ +static const int ads112c14_sinc4_sinc1_pf1_20sps_osr_available[] =3D { + 1600, 12800, 25600, 51200 +}; + +/* Index corresponds to ADS112C14_DEVICE_CFG_SPEED_MODE value. */ +static const int ads112c14_sinc4_sinc1_pf1_25sps_osr_available[] =3D { + 1280, 10240, 20480, 40960 +}; + +/* Index corresponds to ADS112C14_DEVICE_CFG_SPEED_MODE value. */ +static const int ads112c14_fmod_div[] =3D { + 128, 16, 8, 4 +}; + +enum ads112c14_filter_type { + ADS112C14_FILTER_TYPE_SINC4, + ADS112C14_FILTER_TYPE_SINC4_SINC1, + ADS112C14_FILTER_TYPE_SINC4_SINC1_PF1, +}; + +static const char * const ads112c14_filter_type_names[] =3D { + [ADS112C14_FILTER_TYPE_SINC4] =3D "sinc4", + [ADS112C14_FILTER_TYPE_SINC4_SINC1] =3D "sinc4+sinc1", + [ADS112C14_FILTER_TYPE_SINC4_SINC1_PF1] =3D "sinc4+sinc1+pf1", +}; + #define ADS112C14_I2C_CRC8_POLYNOMIAL 0x07 DECLARE_CRC8_TABLE(ads112c14_crc8_table); =20 @@ -202,6 +247,8 @@ enum { ADS112C14_SYS_MON_CHANNEL_SHORT, }; =20 +static const struct iio_chan_spec_ext_info ads112c14_ext_info[]; + static const struct iio_chan_spec ads112c14_sys_mon_channels[] =3D { { .type =3D IIO_TEMP, @@ -210,7 +257,12 @@ static const struct iio_chan_spec ads112c14_sys_mon_ch= annels[] =3D { .address =3D 2, .info_mask_separate =3D BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE) - | BIT(IIO_CHAN_INFO_OFFSET), + | BIT(IIO_CHAN_INFO_OFFSET) + | BIT(IIO_CHAN_INFO_SAMP_FREQ) + | BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), + .info_mask_separate_available =3D BIT(IIO_CHAN_INFO_SAMP_FREQ) + | BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), + .ext_info =3D ads112c14_ext_info, }, { .type =3D IIO_VOLTAGE, @@ -218,7 +270,12 @@ static const struct iio_chan_spec ads112c14_sys_mon_ch= annels[] =3D { .channel =3D ADS112C14_SYS_MON_CHANNEL_EXT_REF, .address =3D 3, .info_mask_separate =3D BIT(IIO_CHAN_INFO_RAW) - | BIT(IIO_CHAN_INFO_SCALE), + | BIT(IIO_CHAN_INFO_SCALE) + | BIT(IIO_CHAN_INFO_SAMP_FREQ) + | BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), + .info_mask_separate_available =3D BIT(IIO_CHAN_INFO_SAMP_FREQ) + | BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), + .ext_info =3D ads112c14_ext_info, }, { .type =3D IIO_VOLTAGE, @@ -226,7 +283,12 @@ static const struct iio_chan_spec ads112c14_sys_mon_ch= annels[] =3D { .channel =3D ADS112C14_SYS_MON_CHANNEL_AVDD, .address =3D 4, .info_mask_separate =3D BIT(IIO_CHAN_INFO_RAW) - | BIT(IIO_CHAN_INFO_SCALE), + | BIT(IIO_CHAN_INFO_SCALE) + | BIT(IIO_CHAN_INFO_SAMP_FREQ) + | BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), + .info_mask_separate_available =3D BIT(IIO_CHAN_INFO_SAMP_FREQ) + | BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), + .ext_info =3D ads112c14_ext_info, }, { .type =3D IIO_VOLTAGE, @@ -234,7 +296,12 @@ static const struct iio_chan_spec ads112c14_sys_mon_ch= annels[] =3D { .channel =3D ADS112C14_SYS_MON_CHANNEL_DVDD, .address =3D 5, .info_mask_separate =3D BIT(IIO_CHAN_INFO_RAW) - | BIT(IIO_CHAN_INFO_SCALE), + | BIT(IIO_CHAN_INFO_SCALE) + | BIT(IIO_CHAN_INFO_SAMP_FREQ) + | BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), + .info_mask_separate_available =3D BIT(IIO_CHAN_INFO_SAMP_FREQ) + | BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), + .ext_info =3D ads112c14_ext_info, }, { .type =3D IIO_VOLTAGE, @@ -244,8 +311,13 @@ static const struct iio_chan_spec ads112c14_sys_mon_ch= annels[] =3D { .differential =3D 1, .address =3D 1, .info_mask_separate =3D BIT(IIO_CHAN_INFO_RAW) - | BIT(IIO_CHAN_INFO_SCALE), - .info_mask_separate_available =3D BIT(IIO_CHAN_INFO_SCALE), + | BIT(IIO_CHAN_INFO_SCALE) + | BIT(IIO_CHAN_INFO_SAMP_FREQ) + | BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), + .info_mask_separate_available =3D BIT(IIO_CHAN_INFO_SCALE) + | BIT(IIO_CHAN_INFO_SAMP_FREQ) + | BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), + .ext_info =3D ads112c14_ext_info, }, }; =20 @@ -265,6 +337,11 @@ struct ads112c14_measurement { int scale_available[ARRAY_SIZE(ads112c14_pga_gains_x10)][2]; }; =20 +struct ads112c14_channel_state { + u8 speed_mode; + u8 filter_osr; +}; + struct ads112c14_data { const struct ads112c14_chip_info *chip_info; struct regmap *regmap; @@ -281,9 +358,13 @@ struct ads112c14_data { bool refn_is_gnd; u32 ext_ref_ohms; struct ads112c14_measurement *measurements; + struct ads112c14_channel_state *channel_states; u32 num_measurements; u8 sys_mon_chan_short_gain_val; int sys_mon_chan_short_scale_available[ARRAY_SIZE(ads112c14_pga_gains_x10= )][2]; + int sinc4_sample_rate_available[ARRAY_SIZE(ads112c14_sinc4_osr_available)= ][ARRAY_SIZE(ads112c14_fmod_div)][2]; + int sinc4_sinc1_sample_rate_available[ARRAY_SIZE(ads112c14_sinc4_sinc1_os= r_available)][ARRAY_SIZE(ads112c14_fmod_div)][2]; + int sinc4_sinc1_pf1_sample_rate_available[2][2]; IIO_DECLARE_BUFFER_WITH_TS(__be32, scan, ADS112C14_MAX_MEASUREMENT_CHANNE= LS + ARRAY_SIZE(ads112c14_sys_mon_channels)); }; @@ -469,14 +550,46 @@ static const struct regmap_config ads112c14_regmap_co= nfig =3D { .cache_type =3D REGCACHE_MAPLE, }; =20 +static int ads112c14_get_osr(struct ads112c14_channel_state *channel_state) +{ + u8 i; + + switch (channel_state->filter_osr) { + case ADS112C14_DATA_RATE_CFG_FLTR_OSR_16...ADS112C14_DATA_RATE_CFG_FLTR_O= SR_32: + i =3D channel_state->filter_osr; + return ads112c14_sinc4_osr_available[i]; + case ADS112C14_DATA_RATE_CFG_FLTR_OSR_128...ADS112C14_DATA_RATE_CFG_FLTR_= OSR_1024: + i =3D channel_state->filter_osr - ADS112C14_DATA_RATE_CFG_FLTR_OSR_128; + return ads112c14_sinc4_sinc1_osr_available[i]; + case ADS112C14_DATA_RATE_CFG_FLTR_OSR_25SPS: + i =3D channel_state->speed_mode; + return ads112c14_sinc4_sinc1_pf1_25sps_osr_available[i]; + case ADS112C14_DATA_RATE_CFG_FLTR_OSR_20SPS: + i =3D channel_state->speed_mode; + return ads112c14_sinc4_sinc1_pf1_20sps_osr_available[i]; + default: + return -EINVAL; + } +} + static int ads112c14_prepare_measurement_channel(struct ads112c14_data *da= ta, const struct iio_chan_spec *chan, bool en_burnout) { struct ads112c14_measurement *measurement =3D &data->measurements[chan->s= can_index]; + struct ads112c14_channel_state *channel_state; u32 refp_buf_en, refn_buf_en, ref_val, ref_sel; int ret; =20 + channel_state =3D &data->channel_states[chan->scan_index]; + + ret =3D regmap_update_bits(data->regmap, ADS112C14_REG_DEVICE_CFG, + ADS112C14_DEVICE_CFG_SPEED_MODE, + FIELD_PREP(ADS112C14_DEVICE_CFG_SPEED_MODE, + channel_state->speed_mode)); + if (ret) + return ret; + ret =3D regmap_update_bits(data->regmap, ADS112C14_REG_MUX_CFG, ADS112C14_MUX_CFG_AINP | ADS112C14_MUX_CFG_AINN, FIELD_PREP(ADS112C14_MUX_CFG_AINP, chan->channel) | @@ -523,9 +636,12 @@ static int ads112c14_prepare_measurement_channel(struc= t ads112c14_data *data, return ret; =20 ret =3D regmap_update_bits(data->regmap, ADS112C14_REG_DATA_RATE_CFG, - ADS112C14_DATA_RATE_CFG_GC_EN, + ADS112C14_DATA_RATE_CFG_GC_EN | + ADS112C14_DATA_RATE_CFG_FLTR_OSR, FIELD_PREP(ADS112C14_DATA_RATE_CFG_GC_EN, - measurement->global_chop && !en_burnout)); + measurement->global_chop && !en_burnout) | + FIELD_PREP(ADS112C14_DATA_RATE_CFG_FLTR_OSR, + channel_state->filter_osr)); if (ret) return ret; =20 @@ -568,9 +684,12 @@ static int ads112c14_prepare_measurement_channel(struc= t ads112c14_data *data, static int ads112c14_prepare_sys_mon_channel(struct ads112c14_data *data, const struct iio_chan_spec *chan) { + struct ads112c14_channel_state *channel_state; u32 gain_val; int ret; =20 + channel_state =3D &data->channel_states[chan->scan_index]; + /* * NB: IDAC registers are left as-is in case they are generating current * needed for the external reference measurement. @@ -597,6 +716,22 @@ static int ads112c14_prepare_sys_mon_channel(struct ad= s112c14_data *data, if (ret) return ret; =20 + ret =3D regmap_update_bits(data->regmap, ADS112C14_REG_DEVICE_CFG, + ADS112C14_DEVICE_CFG_SPEED_MODE, + FIELD_PREP(ADS112C14_DEVICE_CFG_SPEED_MODE, + channel_state->speed_mode)); + if (ret) + return ret; + + ret =3D regmap_update_bits(data->regmap, ADS112C14_REG_DATA_RATE_CFG, + ADS112C14_DATA_RATE_CFG_GC_EN | + ADS112C14_DATA_RATE_CFG_FLTR_OSR, + FIELD_PREP(ADS112C14_DATA_RATE_CFG_GC_EN, 0) | + FIELD_PREP(ADS112C14_DATA_RATE_CFG_FLTR_OSR, + channel_state->filter_osr)); + if (ret) + return ret; + /* * REVISIT: if we implement regulator support for the REFOUT pin, we * might need to make this voltage match what is required by that. In @@ -824,6 +959,45 @@ static int ads112c14_read_raw(struct iio_dev *indio_de= v, */ *val =3D div_s64((s64)(25 * 405 - 119500) * BIT(fsr_bits), vref_uV); return IIO_VAL_INT; + case IIO_CHAN_INFO_SAMP_FREQ: { + struct ads112c14_channel_state *channel_state; + const int (*available)[2]; + u8 i, j; + + guard(mutex)(&data->lock); + + channel_state =3D &data->channel_states[chan->scan_index]; + + switch (channel_state->filter_osr) { + case ADS112C14_DATA_RATE_CFG_FLTR_OSR_16...ADS112C14_DATA_RATE_CFG_FLTR_= OSR_32: + j =3D channel_state->filter_osr; + available =3D data->sinc4_sample_rate_available[j]; + i =3D channel_state->speed_mode; + break; + case ADS112C14_DATA_RATE_CFG_FLTR_OSR_128...ADS112C14_DATA_RATE_CFG_FLTR= _OSR_1024: + j =3D channel_state->filter_osr - ADS112C14_DATA_RATE_CFG_FLTR_OSR_128; + available =3D data->sinc4_sinc1_sample_rate_available[j]; + i =3D channel_state->speed_mode; + break; + case ADS112C14_DATA_RATE_CFG_FLTR_OSR_25SPS: + case ADS112C14_DATA_RATE_CFG_FLTR_OSR_20SPS: + available =3D data->sinc4_sinc1_pf1_sample_rate_available; + i =3D channel_state->filter_osr - ADS112C14_DATA_RATE_CFG_FLTR_OSR_25SP= S; + break; + default: + return -EINVAL; + } + + *val =3D available[i][0]; + *val2 =3D available[i][1]; + return IIO_VAL_INT_PLUS_MICRO; + } + case IIO_CHAN_INFO_OVERSAMPLING_RATIO: { + guard(mutex)(&data->lock); + + *val =3D ads112c14_get_osr(&data->channel_states[chan->scan_index]); + return IIO_VAL_INT; + } default: return -EINVAL; } @@ -834,6 +1008,9 @@ static int ads112c14_read_avail(struct iio_dev *indio_= dev, int *type, int *length, long mask) { struct ads112c14_data *data =3D iio_priv(indio_dev); + struct ads112c14_channel_state *channel_state; + + channel_state =3D &data->channel_states[chan->scan_index]; =20 switch (mask) { case IIO_CHAN_INFO_SCALE: @@ -859,6 +1036,58 @@ static int ads112c14_read_avail(struct iio_dev *indio= _dev, } =20 return -EINVAL; + + case IIO_CHAN_INFO_SAMP_FREQ: { + guard(mutex)(&data->lock); + + switch (channel_state->filter_osr) { + case ADS112C14_DATA_RATE_CFG_FLTR_OSR_16...ADS112C14_DATA_RATE_CFG_FLTR_= OSR_32: + *vals =3D (const int *)data->sinc4_sample_rate_available[channel_state-= >filter_osr]; + *length =3D 2 * ARRAY_SIZE(data->sinc4_sample_rate_available[0]); + *type =3D IIO_VAL_INT_PLUS_MICRO; + return IIO_AVAIL_LIST; + case ADS112C14_DATA_RATE_CFG_FLTR_OSR_128...ADS112C14_DATA_RATE_CFG_FLTR= _OSR_1024: + *vals =3D (const int *)data->sinc4_sinc1_sample_rate_available[channel_= state->filter_osr - ADS112C14_DATA_RATE_CFG_FLTR_OSR_128]; + *length =3D 2 * ARRAY_SIZE(data->sinc4_sinc1_sample_rate_available[0]); + *type =3D IIO_VAL_INT_PLUS_MICRO; + return IIO_AVAIL_LIST; + case ADS112C14_DATA_RATE_CFG_FLTR_OSR_25SPS...ADS112C14_DATA_RATE_CFG_FL= TR_OSR_20SPS: + *vals =3D (const int *)data->sinc4_sinc1_pf1_sample_rate_available; + *length =3D 2 * ARRAY_SIZE(data->sinc4_sinc1_pf1_sample_rate_available); + *type =3D IIO_VAL_INT_PLUS_MICRO; + return IIO_AVAIL_LIST; + default: + return -EINVAL; + } + } + case IIO_CHAN_INFO_OVERSAMPLING_RATIO: { + guard(mutex)(&data->lock); + + switch (channel_state->filter_osr) { + case ADS112C14_DATA_RATE_CFG_FLTR_OSR_16...ADS112C14_DATA_RATE_CFG_FLTR_= OSR_32: + *vals =3D ads112c14_sinc4_osr_available; + *length =3D ARRAY_SIZE(ads112c14_sinc4_osr_available); + *type =3D IIO_VAL_INT; + return IIO_AVAIL_LIST; + case ADS112C14_DATA_RATE_CFG_FLTR_OSR_128...ADS112C14_DATA_RATE_CFG_FLTR= _OSR_1024: + *vals =3D ads112c14_sinc4_sinc1_osr_available; + *length =3D ARRAY_SIZE(ads112c14_sinc4_sinc1_osr_available); + *type =3D IIO_VAL_INT; + return IIO_AVAIL_LIST; + case ADS112C14_DATA_RATE_CFG_FLTR_OSR_25SPS: + *vals =3D ads112c14_sinc4_sinc1_pf1_25sps_osr_available; + *length =3D ARRAY_SIZE(ads112c14_sinc4_sinc1_pf1_25sps_osr_available); + *type =3D IIO_VAL_INT; + return IIO_AVAIL_LIST; + case ADS112C14_DATA_RATE_CFG_FLTR_OSR_20SPS: + *vals =3D ads112c14_sinc4_sinc1_pf1_20sps_osr_available; + *length =3D ARRAY_SIZE(ads112c14_sinc4_sinc1_pf1_20sps_osr_available); + *type =3D IIO_VAL_INT; + return IIO_AVAIL_LIST; + default: + return -EINVAL; + } + } default: return -EINVAL; } @@ -871,6 +1100,7 @@ static int ads112c14_write_raw(struct iio_dev *indio_d= ev, struct ads112c14_data *data =3D iio_priv(indio_dev); const int (*scale_avail)[2]; u8 *gain_val; + u32 i; =20 IIO_DEV_ACQUIRE_DIRECT_MODE(indio_dev, claim); if (IIO_DEV_ACQUIRE_FAILED(claim)) @@ -903,6 +1133,99 @@ static int ads112c14_write_raw(struct iio_dev *indio_= dev, =20 return -EINVAL; } + case IIO_CHAN_INFO_SAMP_FREQ: { + struct ads112c14_channel_state *channel_state; + const int (*available)[2]; + + guard(mutex)(&data->lock); + + channel_state =3D &data->channel_states[chan->scan_index]; + + switch (channel_state->filter_osr) { + case ADS112C14_DATA_RATE_CFG_FLTR_OSR_16...ADS112C14_DATA_RATE_CFG_FLTR_= OSR_1024: + if (channel_state->filter_osr < ADS112C14_DATA_RATE_CFG_FLTR_OSR_128) { + u8 idx =3D channel_state->filter_osr; + + available =3D data->sinc4_sample_rate_available[idx]; + } else { + u8 idx =3D channel_state->filter_osr - ADS112C14_DATA_RATE_CFG_FLTR_OS= R_128; + + available =3D data->sinc4_sinc1_sample_rate_available[idx]; + } + + for (i =3D 0; i < ARRAY_SIZE(ads112c14_fmod_div); i++) { + if (val =3D=3D available[i][0] && val2 =3D=3D available[i][1]) { + channel_state->speed_mode =3D i; + return 0; + } + } + + return -EINVAL; + case ADS112C14_DATA_RATE_CFG_FLTR_OSR_25SPS: + case ADS112C14_DATA_RATE_CFG_FLTR_OSR_20SPS: { + available =3D data->sinc4_sinc1_pf1_sample_rate_available; + + for (i =3D 0; i < ARRAY_SIZE(data->sinc4_sinc1_pf1_sample_rate_availabl= e); i++) { + if (val =3D=3D available[i][0] && val2 =3D=3D available[i][1]) { + channel_state->filter_osr =3D i + ADS112C14_DATA_RATE_CFG_FLTR_OSR_25= SPS; + return 0; + } + } + + return -EINVAL; + } + default: + return -EINVAL; + } + } + case IIO_CHAN_INFO_OVERSAMPLING_RATIO: { + struct ads112c14_channel_state *channel_state; + + guard(mutex)(&data->lock); + + channel_state =3D &data->channel_states[chan->scan_index]; + + switch (channel_state->filter_osr) { + case ADS112C14_DATA_RATE_CFG_FLTR_OSR_16...ADS112C14_DATA_RATE_CFG_FLTR_= OSR_32: + for (i =3D 0; i < ARRAY_SIZE(ads112c14_sinc4_osr_available); i++) { + if (val =3D=3D ads112c14_sinc4_osr_available[i]) { + channel_state->filter_osr =3D i; + return 0; + } + } + + return -EINVAL; + case ADS112C14_DATA_RATE_CFG_FLTR_OSR_128...ADS112C14_DATA_RATE_CFG_FLTR= _OSR_1024: + for (i =3D 0; i < ARRAY_SIZE(ads112c14_sinc4_sinc1_osr_available); i++)= { + if (val =3D=3D ads112c14_sinc4_sinc1_osr_available[i]) { + channel_state->filter_osr =3D i + ADS112C14_DATA_RATE_CFG_FLTR_OSR_12= 8; + return 0; + } + } + + return -EINVAL; + case ADS112C14_DATA_RATE_CFG_FLTR_OSR_25SPS: + for (i =3D 0; i < ARRAY_SIZE(ads112c14_sinc4_sinc1_pf1_25sps_osr_availa= ble); i++) { + if (val =3D=3D ads112c14_sinc4_sinc1_pf1_25sps_osr_available[i]) { + channel_state->speed_mode =3D i; + return 0; + } + } + + return -EINVAL; + case ADS112C14_DATA_RATE_CFG_FLTR_OSR_20SPS: + for (i =3D 0; i < ARRAY_SIZE(ads112c14_sinc4_sinc1_pf1_20sps_osr_availa= ble); i++) { + if (val =3D=3D ads112c14_sinc4_sinc1_pf1_20sps_osr_available[i]) { + channel_state->speed_mode =3D i; + return 0; + } + } + + return -EINVAL; + default: + return -EINVAL; + } + } default: return -EINVAL; } @@ -1035,6 +1358,85 @@ static const struct iio_info ads112c14_info =3D { .read_label =3D ads112c14_read_label, }; =20 +static int ads112c14_get_filter_type_from_state(struct ads112c14_channel_s= tate *channel_state) +{ + switch (channel_state->filter_osr) { + case ADS112C14_DATA_RATE_CFG_FLTR_OSR_16...ADS112C14_DATA_RATE_CFG_FLTR_O= SR_32: + return ADS112C14_FILTER_TYPE_SINC4; + case ADS112C14_DATA_RATE_CFG_FLTR_OSR_128...ADS112C14_DATA_RATE_CFG_FLTR_= OSR_1024: + return ADS112C14_FILTER_TYPE_SINC4_SINC1; + case ADS112C14_DATA_RATE_CFG_FLTR_OSR_25SPS...ADS112C14_DATA_RATE_CFG_FLT= R_OSR_20SPS: + return ADS112C14_FILTER_TYPE_SINC4_SINC1_PF1; + default: + return -EINVAL; + } +} + +static int ads112c14_set_filter_type(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + unsigned int val) +{ + struct ads112c14_data *data =3D iio_priv(indio_dev); + struct ads112c14_channel_state *channel_state; + int ret; + + IIO_DEV_ACQUIRE_DIRECT_MODE(indio_dev, claim); + if (IIO_DEV_ACQUIRE_FAILED(claim)) + return -EBUSY; + + guard(mutex)(&data->lock); + + channel_state =3D &data->channel_states[chan->scan_index]; + + ret =3D ads112c14_get_filter_type_from_state(channel_state); + if (ret < 0) + return ret; + + /* + * channel_state->filter_osr affects multiple attributes, so don't modify + * it if the filter type is already set to the requested value. + */ + if (ret =3D=3D val) + return 0; + + /* Otherwise, pick an arbitrary default for each type. */ + switch (val) { + case ADS112C14_FILTER_TYPE_SINC4: + channel_state->filter_osr =3D ADS112C14_DATA_RATE_CFG_FLTR_OSR_16; + break; + case ADS112C14_FILTER_TYPE_SINC4_SINC1: + channel_state->filter_osr =3D ADS112C14_DATA_RATE_CFG_FLTR_OSR_128; + break; + case ADS112C14_FILTER_TYPE_SINC4_SINC1_PF1: + channel_state->filter_osr =3D ADS112C14_DATA_RATE_CFG_FLTR_OSR_25SPS; + break; + default: + return -EINVAL; + } + + return 0; +} + +static int ads112c14_get_filter_type(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan) +{ + struct ads112c14_data *data =3D iio_priv(indio_dev); + struct ads112c14_channel_state *channel_state; + + guard(mutex)(&data->lock); + + channel_state =3D &data->channel_states[chan->scan_index]; + + return ads112c14_get_filter_type_from_state(channel_state); +} + +static const struct iio_enum ads112c14_filter_type_enum =3D { + .items =3D ads112c14_filter_type_names, + .num_items =3D ARRAY_SIZE(ads112c14_filter_type_names), + .set =3D ads112c14_set_filter_type, + .get =3D ads112c14_get_filter_type, +}; + static bool ads112c14_using_drdy_trigger(struct iio_dev *indio_dev) { struct ads112c14_data *data =3D iio_priv(indio_dev); @@ -1182,11 +1584,19 @@ static ssize_t ads112c14_read_burnout_raw(struct ii= o_dev *indio_dev, return sysfs_emit(buf, "%d\n", val); } =20 +static const struct iio_chan_spec_ext_info ads112c14_ext_info[] =3D { + IIO_ENUM("filter_type", IIO_SEPARATE, &ads112c14_filter_type_enum), + IIO_ENUM_AVAILABLE("filter_type", IIO_SEPARATE, &ads112c14_filter_type_en= um), + { } +}; + static const struct iio_chan_spec_ext_info ads112c14_ext_info_burnout[] = =3D { { .name =3D "burnoutraw", .read =3D ads112c14_read_burnout_raw, }, + IIO_ENUM("filter_type", IIO_SEPARATE, &ads112c14_filter_type_enum), + IIO_ENUM_AVAILABLE("filter_type", IIO_SEPARATE, &ads112c14_filter_type_en= um), { } }; =20 @@ -1212,7 +1622,7 @@ static int ads112c14_parse_channels(struct iio_dev *i= ndio_dev, struct ads112c14_data *data =3D iio_priv(indio_dev); struct device *dev =3D indio_dev->dev.parent; struct iio_chan_spec *channels; - u32 num_child_nodes, i, pair[2]; + u32 num_child_nodes, num_data_chans, i, pair[2]; int ret; =20 *need_avdd_ref =3D false; @@ -1225,8 +1635,15 @@ static int ads112c14_parse_channels(struct iio_dev *= indio_dev, if (!data->measurements) return -ENOMEM; =20 - channels =3D devm_kcalloc(dev, num_child_nodes + - ARRAY_SIZE(ads112c14_sys_mon_channels) + 1, + num_data_chans =3D num_child_nodes + ARRAY_SIZE(ads112c14_sys_mon_channel= s); + + data->channel_states =3D devm_kcalloc(dev, num_data_chans, + sizeof(*data->channel_states), + GFP_KERNEL); + if (!data->channel_states) + return -ENOMEM; + + channels =3D devm_kcalloc(dev, num_data_chans + 1, sizeof(*channels), GFP_KERNEL); if (!channels) return -ENOMEM; @@ -1238,7 +1655,9 @@ static int ads112c14_parse_channels(struct iio_dev *i= ndio_dev, =20 spec->indexed =3D 1; spec->scan_index =3D i; + spec->ext_info =3D ads112c14_ext_info; measurement->gain_val =3D 1; + data->channel_states[i].filter_osr =3D ADS112C14_DATA_RATE_CFG_FLTR_OSR_= 16; =20 if (fwnode_property_present(child, "label")) { ret =3D fwnode_property_read_string(child, "label", &measurement->label= ); @@ -1402,8 +1821,13 @@ static int ads112c14_parse_channels(struct iio_dev *= indio_dev, if (measurement->vref_source =3D=3D ADS112C14_VREF_SOURCE_EXTERNAL) *need_ext_ref =3D true; =20 - spec->info_mask_separate =3D BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_= SCALE); - spec->info_mask_separate_available =3D BIT(IIO_CHAN_INFO_SCALE); + spec->info_mask_separate =3D BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_SCALE) | + BIT(IIO_CHAN_INFO_SAMP_FREQ) | + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO); + spec->info_mask_separate_available =3D BIT(IIO_CHAN_INFO_SCALE) | + BIT(IIO_CHAN_INFO_SAMP_FREQ) | + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO); =20 /* * If reference source is resistor rather than voltage supply, @@ -1437,6 +1861,10 @@ static int ads112c14_parse_channels(struct iio_dev *= indio_dev, =20 for (u32 j =3D 0; j < ARRAY_SIZE(ads112c14_sys_mon_channels); j++) { struct iio_chan_spec *spec =3D &channels[i]; + struct ads112c14_channel_state *channel_state; + + channel_state =3D &data->channel_states[i]; + channel_state->filter_osr =3D ADS112C14_DATA_RATE_CFG_FLTR_OSR_16; =20 /* Update the template that was already copied with dynamic values. */ spec->scan_index =3D i; @@ -1475,6 +1903,44 @@ static void ads112c14_populate_scale_available(int (= *scale_avail)[2], } } =20 +static void ads112c14_populate_odr_tables(struct ads112c14_data *data) +{ + int *available; + u32 osr, fmod_Hz; + u64 odr_uHz; + u32 i, j; + + for (i =3D 0; i < ARRAY_SIZE(ads112c14_sinc4_osr_available); i++) { + osr =3D ads112c14_sinc4_osr_available[i]; + + for (j =3D 0; j < ARRAY_SIZE(ads112c14_fmod_div); j++) { + fmod_Hz =3D data->fclk_Hz / ads112c14_fmod_div[j]; + odr_uHz =3D div_u64((u64)fmod_Hz * MICRO, osr); + available =3D data->sinc4_sample_rate_available[i][j]; + available[0] =3D div_u64_rem(odr_uHz, MICRO, &available[1]); + } + } + + for (i =3D 0; i < ARRAY_SIZE(ads112c14_sinc4_sinc1_osr_available); i++) { + osr =3D ads112c14_sinc4_sinc1_osr_available[i]; + + for (j =3D 0; j < ARRAY_SIZE(ads112c14_fmod_div); j++) { + fmod_Hz =3D data->fclk_Hz / ads112c14_fmod_div[j]; + odr_uHz =3D div_u64((u64)fmod_Hz * MICRO, osr); + available =3D data->sinc4_sinc1_sample_rate_available[i][j]; + available[0] =3D div_u64_rem(odr_uHz, MICRO, &available[1]); + } + } + + odr_uHz =3D div_u64((u64)25 * data->fclk_Hz * MICRO, ADS112C14_INTERNAL_C= LK_Hz); + available =3D data->sinc4_sinc1_pf1_sample_rate_available[0]; + available[0] =3D div_u64_rem(odr_uHz, MICRO, &available[1]); + + odr_uHz =3D div_u64((u64)20 * data->fclk_Hz * MICRO, ADS112C14_INTERNAL_C= LK_Hz); + available =3D data->sinc4_sinc1_pf1_sample_rate_available[1]; + available[0] =3D div_u64_rem(odr_uHz, MICRO, &available[1]); +} + static void ads112c14_populate_tables(struct ads112c14_data *data) { u32 full_scale, fsr_bits; @@ -1512,6 +1978,7 @@ static void ads112c14_populate_tables(struct ads112c1= 4_data *data) =20 ads112c14_populate_scale_available(data->sys_mon_chan_short_scale_availab= le, full_scale, fsr_bits); + ads112c14_populate_odr_tables(data); } =20 static int ads112c14_probe(struct i2c_client *client) --=20 2.43.0 From nobody Tue Sep 29 11:58:32 2026 Received: from mail-ot1-f51.google.com (mail-ot1-f51.google.com [209.85.210.51]) (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 C30A423ED60 for ; Sat, 8 Aug 2026 00:20:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.51 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786148440; cv=none; b=tCCDjfO8DYsHZJ16NRBjCWGRcsKH4GdaVgD7/KSyUNUF0SEU4ZhwztfOnkCzGm20QpjR4F+tzf2EcYu4BoQUUr+0w/MdfA3pjK7vGL2wXiYMmo8ERz7gloI8pCn/BGBRwt/UjUGkv6nhYeePn5mmi6QPR8Bk08oM8w9+tUOrR2I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786148440; c=relaxed/simple; bh=ESa4zgB82WDyEdoFZl9mN7qSJr3JEOf6jr0xy6ffzxo=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=qtMrrO1It3bYHrhrwwyHM5syHGk+NH8SViypqZBbAtozQuVD8Los/Oeu+fzdeWjDqPcRH9TjwGD0jUKM490toYxLuZKQL5b1u8SwMrjjamOrW590Gjr5uTz540iMVmTqiy0SG25uq/vXptKMZY3fGkUQ95slMdLaxMqbob7GB/w= 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 header.i=@baylibre.com header.b=j2Ozjz3w; arc=none smtp.client-ip=209.85.210.51 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 header.i=@baylibre.com header.b="j2Ozjz3w" Received: by mail-ot1-f51.google.com with SMTP id 46e09a7af769-7e9fc3de7ceso63431a34.1 for ; Fri, 07 Aug 2026 17:20:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre.com; s=google; t=1786148438; x=1786753238; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=hwqpzP24UA2fHMTxYLSqDw69rK/fygGat0tgP1v59qc=; b=j2Ozjz3w6czFxiX7H2hMRiFOfVV/UKvJgFYAKBr2qtBlU8m0dT2IWQgUnBpcuFMLlh MvlyGKx0wQy5j3hBsSxFrQfuUHY/1RoIXUv7nRxR6DB9ZBYFqfgNWbL2DbRkB6pHHuj8 pIAjYg/aX014Y16ypuAoS28wMfzTKsFqCjGC0ua5Vukd7IWIaq+EdCeuMHWTFLMOWLz9 sEEcaq2bA59MBBenZIXRzLQ0a+glBz0a89nJJ2CYInUrqnyVvuHpvPIhf+I4mA21l+WV SfORAKcC1nx76+koaiDof47MDzKGvHwgze4K92OTCdAnzOg0sFXoI6Rur3M26oR4MnVD tC/Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1786148438; x=1786753238; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=hwqpzP24UA2fHMTxYLSqDw69rK/fygGat0tgP1v59qc=; b=HIUlU7UDNQ/Bhj/FQVDRHXTIe5Db4t+fWVtfKMZTlggoTfecLUpeIDmQ4t6U1FhipN 0IJ5CeXQthHIuhmvrfHnnFG5LNrqtBubWf8ek3nBxY1/1IPbIQIT/KsjL43Cy89WagRr PHbiRDgxVEnKHXRcQOJfHKuhSMZiCmW0GuSgK1nn5ejGaVVeG8gZ1b7IS0KcPBbSDqm0 SQ/U6hPHwZSVD4WdY/Yep2cVcdSVS9OhyOM3C8vjf6OfnwQoiPbm1xigxw3ONMJHbhG3 DPlb5zXpCBgcGb1PHhmk13VPT24L68tzN/9YkViF9L/zN/pA0G2d9WLfVa+dE/v1tnyI mNUg== X-Forwarded-Encrypted: i=1; AHgh+RpKIp5j28qgJiYRpymZhVw301rx3M4xwzAwRp7MDxeNV3a6olk+8tC9eB789GbIuG0+LlkFAQoi+G/ngFM=@vger.kernel.org X-Gm-Message-State: AOJu0YwQEZCiPgNuvtdDzA3fA7yIRs5UR55I7Gu9bZkbiNKrONkkIats T76Xe8be3z6qpMZKK7pekC6+kLzj9EZy2Hkbf5V7IIwGNAp+SIfqofKOzssl3DI/BYo= X-Gm-Gg: AR+sD13kVTHbjHxyf421ZeCLYTOUNwI2vMAuPcPfpvgTifwpPr4e3TWY0zV/IAHwnGj hs70be6dwCF2udlfqjXchx4MjzlgQNw1qpcfh9ZHJXKaDKHEWI8zW4FmQS8aK2cePbl6yj9pGOZ XA5XCIY3wqgaVukRoBPGnAEvRF2VEzUnb33ORgRGnhgUomPBO2rw+/fXan+XtPgK0pVJe4YPwK6 1j8/cffwn9pfGG2mDR/LGz6CanlEouEWeui+nM3Fy+JcRoXs7AmbEIkSeML+X1l19ROmRgRGBOh QZ7555mwTICEBXgzHx0U+kY0G+5eYFEwesM36UDxi+BjAXiY9rG3wwLTonDi5Lmwb7Ez7TKp+8g n0sh1GhFZoc83uH9mdXYWHy/ZHX3J/ScZZjJ3wdRndSOqnBBUPh0bFMpxXCKPRxdMulsXs//I/Z TmhkSx9vIGKt032Rbv7xbPBA4zuo79wpONwJxBEEKqRMfVi+v6rY73kH68DmCFudKv X-Received: by 2002:a05:6830:448d:b0:7e6:d54e:8fe3 with SMTP id 46e09a7af769-7f36930b186mr2604615a34.9.1786148437608; Fri, 07 Aug 2026 17:20:37 -0700 (PDT) Received: from [127.0.1.1] ([2600:8803:e7e4:500:b714:88c:313d:dee2]) by smtp.gmail.com with ESMTPSA id 46e09a7af769-7f35b5a7616sm2526147a34.8.2026.08.07.17.20.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 07 Aug 2026 17:20:36 -0700 (PDT) From: "David Lechner (TI)" Date: Fri, 07 Aug 2026 19:19:48 -0500 Subject: [PATCH 3/5] iio: ABI: add sinc4+sinc1+pf1 filter_type 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: <20260807-iio-adc-ti-ads112c14-filter-support-v1-3-4d3ba00caf18@baylibre.com> References: <20260807-iio-adc-ti-ads112c14-filter-support-v1-0-4d3ba00caf18@baylibre.com> In-Reply-To: <20260807-iio-adc-ti-ads112c14-filter-support-v1-0-4d3ba00caf18@baylibre.com> To: Jonathan Cameron , =?utf-8?q?Nuno_S=C3=A1?= , Andy Shevchenko Cc: linux-iio@vger.kernel.org, linux-kernel@vger.kernel.org, "David Lechner (TI)" X-Mailer: b4 0.17-dev X-Developer-Signature: v=1; a=openpgp-sha256; l=6722; i=dlechner@baylibre.com; h=from:subject:message-id; bh=ESa4zgB82WDyEdoFZl9mN7qSJr3JEOf6jr0xy6ffzxo=; b=owEBbQGS/pANAwAKAcLMIAH/AY/AAcsmYgBqdnY9VmoK+wsHJrd6IjBuaHdBr2aALTp3eILjc 7FGg/lccbOJATMEAAEKAB0WIQTsGNmeYg6D1pzYaJjCzCAB/wGPwAUCanZ2PQAKCRDCzCAB/wGP wK7ZB/9ZTfRPMU+xIVCYWke9cKsEjHUv2+My+RrDzWjeqx2pmsQPy5E9AcnqMHf2V4eFZ2lb6l2 USu7n9fim9fLzFzYMU+S0bUb66106UVF92U2cI63Lh7INABJWfsG4j8nhT1UCeTpr+8xc0wEX6f DXPk0bHf3UZ5y1S4yOzA+LKLPEeoThK+5HG/SRAaf5uoW1vfWq2nD247lideZuCVshacEWgy3lr 7YpWdcT3NZI7ZK+rYQXGC0WAuFBCyjrfh28dJSGDWmf2lEGxzFkgPcnI2h4AqtveVFgVNOJvvnR D/lCUJ04OpyW26yjpICLR1C+5YdBtsP2Scpk4iLqBo5eKhfF X-Developer-Key: i=dlechner@baylibre.com; a=openpgp; fpr=8A73D82A6A1F509907F373881F8AF88C82F77C03 Document "sinc4+sinc1+pf1" as a valid value for the filter_type attributes (used by the ti-ads112c14 driver). Signed-off-by: David Lechner (TI) --- Documentation/ABI/testing/sysfs-bus-iio | 1 + drivers/iio/adc/ti-ads112c14.c | 158 ++++++++++++++++------------= ---- 2 files changed, 80 insertions(+), 79 deletions(-) diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/te= sting/sysfs-bus-iio index a4f5595722ad..a8e1cb8e7490 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio +++ b/Documentation/ABI/testing/sysfs-bus-iio @@ -2380,6 +2380,7 @@ Description: * "sinc4+lp" - Sinc4 + Low Pass Filter. * "sinc4+sinc1" - Sinc4 + averaging by 8. Low 1st conversion time. + * "sinc4+sinc1+pf1" - Sinc4 + Sinc1 + device specific Post Filter 1. * "sinc4+rej60" - Sinc4 + 60Hz rejection. * "sinc5" - The digital sinc5 filter. Excellent noise performance diff --git a/drivers/iio/adc/ti-ads112c14.c b/drivers/iio/adc/ti-ads112c14.c index a73c0d6f0f65..ff22d0716abe 100644 --- a/drivers/iio/adc/ti-ads112c14.c +++ b/drivers/iio/adc/ti-ads112c14.c @@ -1358,85 +1358,6 @@ static const struct iio_info ads112c14_info =3D { .read_label =3D ads112c14_read_label, }; =20 -static int ads112c14_get_filter_type_from_state(struct ads112c14_channel_s= tate *channel_state) -{ - switch (channel_state->filter_osr) { - case ADS112C14_DATA_RATE_CFG_FLTR_OSR_16...ADS112C14_DATA_RATE_CFG_FLTR_O= SR_32: - return ADS112C14_FILTER_TYPE_SINC4; - case ADS112C14_DATA_RATE_CFG_FLTR_OSR_128...ADS112C14_DATA_RATE_CFG_FLTR_= OSR_1024: - return ADS112C14_FILTER_TYPE_SINC4_SINC1; - case ADS112C14_DATA_RATE_CFG_FLTR_OSR_25SPS...ADS112C14_DATA_RATE_CFG_FLT= R_OSR_20SPS: - return ADS112C14_FILTER_TYPE_SINC4_SINC1_PF1; - default: - return -EINVAL; - } -} - -static int ads112c14_set_filter_type(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, - unsigned int val) -{ - struct ads112c14_data *data =3D iio_priv(indio_dev); - struct ads112c14_channel_state *channel_state; - int ret; - - IIO_DEV_ACQUIRE_DIRECT_MODE(indio_dev, claim); - if (IIO_DEV_ACQUIRE_FAILED(claim)) - return -EBUSY; - - guard(mutex)(&data->lock); - - channel_state =3D &data->channel_states[chan->scan_index]; - - ret =3D ads112c14_get_filter_type_from_state(channel_state); - if (ret < 0) - return ret; - - /* - * channel_state->filter_osr affects multiple attributes, so don't modify - * it if the filter type is already set to the requested value. - */ - if (ret =3D=3D val) - return 0; - - /* Otherwise, pick an arbitrary default for each type. */ - switch (val) { - case ADS112C14_FILTER_TYPE_SINC4: - channel_state->filter_osr =3D ADS112C14_DATA_RATE_CFG_FLTR_OSR_16; - break; - case ADS112C14_FILTER_TYPE_SINC4_SINC1: - channel_state->filter_osr =3D ADS112C14_DATA_RATE_CFG_FLTR_OSR_128; - break; - case ADS112C14_FILTER_TYPE_SINC4_SINC1_PF1: - channel_state->filter_osr =3D ADS112C14_DATA_RATE_CFG_FLTR_OSR_25SPS; - break; - default: - return -EINVAL; - } - - return 0; -} - -static int ads112c14_get_filter_type(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan) -{ - struct ads112c14_data *data =3D iio_priv(indio_dev); - struct ads112c14_channel_state *channel_state; - - guard(mutex)(&data->lock); - - channel_state =3D &data->channel_states[chan->scan_index]; - - return ads112c14_get_filter_type_from_state(channel_state); -} - -static const struct iio_enum ads112c14_filter_type_enum =3D { - .items =3D ads112c14_filter_type_names, - .num_items =3D ARRAY_SIZE(ads112c14_filter_type_names), - .set =3D ads112c14_set_filter_type, - .get =3D ads112c14_get_filter_type, -}; - static bool ads112c14_using_drdy_trigger(struct iio_dev *indio_dev) { struct ads112c14_data *data =3D iio_priv(indio_dev); @@ -1584,6 +1505,85 @@ static ssize_t ads112c14_read_burnout_raw(struct iio= _dev *indio_dev, return sysfs_emit(buf, "%d\n", val); } =20 +static int ads112c14_get_filter_type_from_state(struct ads112c14_channel_s= tate *channel_state) +{ + switch (channel_state->filter_osr) { + case ADS112C14_DATA_RATE_CFG_FLTR_OSR_16...ADS112C14_DATA_RATE_CFG_FLTR_O= SR_32: + return ADS112C14_FILTER_TYPE_SINC4; + case ADS112C14_DATA_RATE_CFG_FLTR_OSR_128...ADS112C14_DATA_RATE_CFG_FLTR_= OSR_1024: + return ADS112C14_FILTER_TYPE_SINC4_SINC1; + case ADS112C14_DATA_RATE_CFG_FLTR_OSR_25SPS...ADS112C14_DATA_RATE_CFG_FLT= R_OSR_20SPS: + return ADS112C14_FILTER_TYPE_SINC4_SINC1_PF1; + default: + return -EINVAL; + } +} + +static int ads112c14_set_filter_type(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + unsigned int val) +{ + struct ads112c14_data *data =3D iio_priv(indio_dev); + struct ads112c14_channel_state *channel_state; + int ret; + + IIO_DEV_ACQUIRE_DIRECT_MODE(indio_dev, claim); + if (IIO_DEV_ACQUIRE_FAILED(claim)) + return -EBUSY; + + guard(mutex)(&data->lock); + + channel_state =3D &data->channel_states[chan->scan_index]; + + ret =3D ads112c14_get_filter_type_from_state(channel_state); + if (ret < 0) + return ret; + + /* + * channel_state->filter_osr affects multiple attributes, so don't modify + * it if the filter type is already set to the requested value. + */ + if (ret =3D=3D val) + return 0; + + /* Otherwise, pick an arbitrary default for each type. */ + switch (val) { + case ADS112C14_FILTER_TYPE_SINC4: + channel_state->filter_osr =3D ADS112C14_DATA_RATE_CFG_FLTR_OSR_16; + break; + case ADS112C14_FILTER_TYPE_SINC4_SINC1: + channel_state->filter_osr =3D ADS112C14_DATA_RATE_CFG_FLTR_OSR_128; + break; + case ADS112C14_FILTER_TYPE_SINC4_SINC1_PF1: + channel_state->filter_osr =3D ADS112C14_DATA_RATE_CFG_FLTR_OSR_25SPS; + break; + default: + return -EINVAL; + } + + return 0; +} + +static int ads112c14_get_filter_type(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan) +{ + struct ads112c14_data *data =3D iio_priv(indio_dev); + struct ads112c14_channel_state *channel_state; + + guard(mutex)(&data->lock); + + channel_state =3D &data->channel_states[chan->scan_index]; + + return ads112c14_get_filter_type_from_state(channel_state); +} + +static const struct iio_enum ads112c14_filter_type_enum =3D { + .items =3D ads112c14_filter_type_names, + .num_items =3D ARRAY_SIZE(ads112c14_filter_type_names), + .set =3D ads112c14_set_filter_type, + .get =3D ads112c14_get_filter_type, +}; + static const struct iio_chan_spec_ext_info ads112c14_ext_info[] =3D { IIO_ENUM("filter_type", IIO_SEPARATE, &ads112c14_filter_type_enum), IIO_ENUM_AVAILABLE("filter_type", IIO_SEPARATE, &ads112c14_filter_type_en= um), --=20 2.43.0 From nobody Tue Sep 29 11:58:32 2026 Received: from mail-ot1-f52.google.com (mail-ot1-f52.google.com [209.85.210.52]) (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 C8C8426461F for ; Sat, 8 Aug 2026 00:20:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.52 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786148446; cv=none; b=d4yizvEtyivzJQg4YfrM9niTEe08kHZ2+0CWLBD/Vq/cMAC8ID+GuTHsbt7CVCm+0WbV9dzdNc+If4KDutv4MGcWCjQ+TeSpX7Ig2ks8JZSwa1tu2wwBaWeru6iFMhZRiafLvbVxmNTID8YO2cp3Nyr21kdBtRLW3dd29ISvOa0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786148446; c=relaxed/simple; bh=IwnR0LQHwDRPXs6QST6dobuzDg033S2O1RJD1JsTEfU=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=pfVsl3xT+4pXCCkJp44My0I5op5XZ6iuCCRIl+nWzYlItmVSAa5N9cNvJ95h2YdPHtKbWM/HLrewkHqNaG6uRTB7vC9yRZ2EfZy+VkSwNczjfWOHvVUqozOoWwfO9k0/fGBEMdf5QBkyvYjrM0ZAYwnNpzhkC7NIchIWm9rIksU= 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 header.i=@baylibre.com header.b=Sa9cYSLv; arc=none smtp.client-ip=209.85.210.52 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 header.i=@baylibre.com header.b="Sa9cYSLv" Received: by mail-ot1-f52.google.com with SMTP id 46e09a7af769-7e9ecb1e13cso159482a34.3 for ; Fri, 07 Aug 2026 17:20:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre.com; s=google; t=1786148440; x=1786753240; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=5VxLVo9Nq9ehTo+s66CGHA4VBpR7u7IyPk4sGMVvasY=; b=Sa9cYSLvTH5LWLKMsTkadQIU60Cg1Yk32ozltxSDQZQ/16qlSU4wsCMirmfxYTqRJ9 N+mg5NMNzd2tndtGjplF2DtrSf2IcCLwRE2vtk2A0SfxJZRiCnmdVt9afws3WBzcTL5f JhbuS50uIQ/4LKl5Y3Jf2pgP+q5E1jCo/TlR1hvkfTk97sAJIGUgLG0h+QQB83OMLO/v ofmO8PI+NCLqHuZD4WGOHfu16HDr8rQblvlm8gGnZnbZvD7U9EjvHd7zgJjkL1TP52pl UtWLwNYYNay3I/KAiRd6XJj0FLLSSs9dwWuMf9Y0Qpqi6rB1Z2EwkMig2cY0HzE3c/me 5org== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1786148440; x=1786753240; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=5VxLVo9Nq9ehTo+s66CGHA4VBpR7u7IyPk4sGMVvasY=; b=YA91cGvEM0WnFMdpASrzH+p0axnmVQl8PCSUMeMMw/lmd66Jo0tf/9BR6jlBVT6uZS UMe8UAzfCK6YoS3hye5zX6hg0o4wWWvJt0gMkViTOt4VcmS3hQuqK4LZjPPeSTxQXLmU 4O59NwnmcjX6E7wbLl0MzAPr2iJXNTGMXuSTfJ4Cdmb8kyLI2Trp4tMhJmDYJyyTF55Y ZbaKpKs7JRWsrPWVZOsWbhFtuK9xyZVRe5p+zCZKtFdFhpK0e3EUxsaegQUWbyu82JSR 7QtEc51Kr12ryBwNDpNA7RVVPnVi1f+bT7e+Y+fbrb2mPfAGf2tc5p/LNW9q4e/QjBFT +Wfw== X-Forwarded-Encrypted: i=1; AHgh+RqHA3prkUraQCrsFgygomN/A6+uche66jRfGHo6tuiM7G0ATqo/T8/hkOB63rY+BzK8tLj7pCe9CANhBbU=@vger.kernel.org X-Gm-Message-State: AOJu0YxJndxkjdmsqqAtlOOMosmOcN9HdiZG0KNMbrtcxWs2hDAIA/Zu bJeHHKLtFdsikmOpNE/Dwqw7DYjz/vO7DZeURh9uIMpkg42E7zOAIUqvECrqKxSMXhg= X-Gm-Gg: AR+sD11xyODjqqauYM2hwGYX71M/mO6h2NvE/calbevslZvMJGmG6nAYULxsmQgHbKc 7W0zDjVEfIKlkqs8NyYa6JfTmCApKaf9BPdDH/xxR3KSeM5dVLvPve+hZTBFThXmCmGNrNU7dsK VhjVcg8vKNmcJeB71Z2E1uKEuIpW8/BDHViZqMQ3DVUS1kByQyB5KZD/vXZ5U3/N4QBPkryYou8 RmOIsSKIDr620G1SQX87N8HK4CfEHRH12d9q97A1+AKR8qJR4j+Q2THcJsPjRrO8KOBM/C9RpUR CdPZs5ytnyr+E6dPU7o4hwR6bIfBdgDjG4hwUbTdTwpWLMfwTUUoYTbraVsR2i/A8Azi+7LDoPK 92VUnxqKPvazvsT+GjT9O5nMl3AbFkBbxEfUQwfbqhisbyJyzqtzsZnTjrMCjbaKM4HMTmUViru uvIlBo8U+bYR2cN6fd7oEOO4zTGm93lcFscqVip1/EDBh93BmrpLEP++OyU+R0gPEUlTy814qmn J0= X-Received: by 2002:a05:6830:6284:b0:7e9:dd7f:7a83 with SMTP id 46e09a7af769-7f1e59bc269mr18776793a34.0.1786148439685; Fri, 07 Aug 2026 17:20:39 -0700 (PDT) Received: from [127.0.1.1] ([2600:8803:e7e4:500:b714:88c:313d:dee2]) by smtp.gmail.com with ESMTPSA id 46e09a7af769-7f35b5a7616sm2526147a34.8.2026.08.07.17.20.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 07 Aug 2026 17:20:39 -0700 (PDT) From: "David Lechner (TI)" Date: Fri, 07 Aug 2026 19:19:49 -0500 Subject: [PATCH 4/5] iio: adc: ti-ads112c14: add settlingtime attribute 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: <20260807-iio-adc-ti-ads112c14-filter-support-v1-4-4d3ba00caf18@baylibre.com> References: <20260807-iio-adc-ti-ads112c14-filter-support-v1-0-4d3ba00caf18@baylibre.com> In-Reply-To: <20260807-iio-adc-ti-ads112c14-filter-support-v1-0-4d3ba00caf18@baylibre.com> To: Jonathan Cameron , =?utf-8?q?Nuno_S=C3=A1?= , Andy Shevchenko Cc: linux-iio@vger.kernel.org, linux-kernel@vger.kernel.org, "David Lechner (TI)" X-Mailer: b4 0.17-dev X-Developer-Signature: v=1; a=openpgp-sha256; l=16366; i=dlechner@baylibre.com; h=from:subject:message-id; bh=IwnR0LQHwDRPXs6QST6dobuzDg033S2O1RJD1JsTEfU=; b=owEBbQGS/pANAwAKAcLMIAH/AY/AAcsmYgBqdnZD/pGI5iz3Z8wQEUjq4wFYLKV3/VH4+q4rl O/G93igzymJATMEAAEKAB0WIQTsGNmeYg6D1pzYaJjCzCAB/wGPwAUCanZ2QwAKCRDCzCAB/wGP wKbaB/9GTOM4ElhpJ2Mdoc0ZKg5aYbPRuCBgNOFS8Wu0UtReRTqLhmmtbRKimYh+wyZKPzSxX9K 7TaawmtmyZycpw+uC+eQAUX6oSB3hGYc4yD5ReG6jbNne+cD++eLq2qjKp58CZ7bqaPC5G0u7dI PnS780v/lgMdWxTFeC60lIkukoqSI0dhYNv+QzXW58RFRl+JheeQvzqGvQ0SiMwQOZXAXfkwqDb kgw2WrvBwlFCO4Vy+F4er2VP/gG/o9J2hJ6XK61g59LiCZsAsUhTTdOiQ8TLaopCFjvM0x2oMUY pR1M0s1xoPuMkypUI1g3NFJ7zvpmZWFydr9AqedrQtgibJTo X-Developer-Key: i=dlechner@baylibre.com; a=openpgp; fpr=8A73D82A6A1F509907F373881F8AF88C82F77C03 Add per-channel sysfs attributes for settlingtime and settlingtime_available. These allow adjusting the total settling time for each channel. The value consists of a fixed t_latency time (based on the selected filter_type, oversampling_ratio and sampling_frequency) plus a user-configurable t_delay that determines the value to write to the DELAY field in the registers. The allowable values are non-linear integer multiples, so the step size is just the smallest step size. Writing the attribute will match the closest matching value for the DELAY field with a time equal to or greater than the requested settling time (unless the requested time is larger than the maximum allowable settling time). Signed-off-by: David Lechner (TI) --- drivers/iio/adc/ti-ads112c14.c | 337 +++++++++++++++++++++++++++++++++++++= +++- 1 file changed, 331 insertions(+), 6 deletions(-) diff --git a/drivers/iio/adc/ti-ads112c14.c b/drivers/iio/adc/ti-ads112c14.c index ff22d0716abe..4cac552bb522 100644 --- a/drivers/iio/adc/ti-ads112c14.c +++ b/drivers/iio/adc/ti-ads112c14.c @@ -214,6 +214,24 @@ static const int ads112c14_fmod_div[] =3D { 128, 16, 8, 4 }; =20 +#define ADS112C14_DELAY_MAX FIELD_MAX(ADS112C14_DATA_RATE_CFG_DELAY) + +/* Table 7-6 latency in t_MOD for OSR [16, 32, 128, 256, 512, 1024]. */ +static const int ads112c14_sinc_latency_tmod[][ARRAY_SIZE(ads112c14_fmod_d= iv)] =3D { + { 80, 88, 88, 104 }, + { 144, 152, 152, 168 }, + { 240, 248, 248, 264 }, + { 368, 376, 376, 392 }, + { 624, 632, 632, 648 }, + { 1136, 1144, 1144, 1160 }, +}; + +/* Table 7-7 latency in t_MOD for output data rates [25SPS, 20SPS]. */ +static const int ads112c14_fir_latency_tmod[][ARRAY_SIZE(ads112c14_fmod_di= v)] =3D { + { 1416, 10384, 20624, 41120 }, + { 1736, 12944, 25744, 51360 }, +}; + enum ads112c14_filter_type { ADS112C14_FILTER_TYPE_SINC4, ADS112C14_FILTER_TYPE_SINC4_SINC1, @@ -340,6 +358,7 @@ struct ads112c14_measurement { struct ads112c14_channel_state { u8 speed_mode; u8 filter_osr; + u8 delay; }; =20 struct ads112c14_data { @@ -365,6 +384,8 @@ struct ads112c14_data { int sinc4_sample_rate_available[ARRAY_SIZE(ads112c14_sinc4_osr_available)= ][ARRAY_SIZE(ads112c14_fmod_div)][2]; int sinc4_sinc1_sample_rate_available[ARRAY_SIZE(ads112c14_sinc4_sinc1_os= r_available)][ARRAY_SIZE(ads112c14_fmod_div)][2]; int sinc4_sinc1_pf1_sample_rate_available[2][2]; + int sinc_settling_time_range_available[ARRAY_SIZE(ads112c14_sinc_latency_= tmod)][ARRAY_SIZE(ads112c14_fmod_div)][3][2]; + int fir_settling_time_range_available[ARRAY_SIZE(ads112c14_fir_latency_tm= od)][ARRAY_SIZE(ads112c14_fmod_div)][3][2]; IIO_DECLARE_BUFFER_WITH_TS(__be32, scan, ADS112C14_MAX_MEASUREMENT_CHANNE= LS + ARRAY_SIZE(ads112c14_sys_mon_channels)); }; @@ -572,6 +593,211 @@ static int ads112c14_get_osr(struct ads112c14_channel= _state *channel_state) } } =20 +static int ads112c14_get_fmod_Hz(struct ads112c14_data *data, + struct ads112c14_channel_state *channel_state) +{ + return data->fclk_Hz / ads112c14_fmod_div[channel_state->speed_mode]; +} + +static int ads112c14_delay_to_tmod(u8 delay) +{ + if (!delay) + return 0; + + return BIT(delay - 1); +} + +static int ads112c14_get_latency_tmod(struct ads112c14_channel_state *chan= nel_state) +{ + u8 speed_mode =3D channel_state->speed_mode; + u8 filter_osr =3D channel_state->filter_osr; + + if (speed_mode >=3D ARRAY_SIZE(ads112c14_fmod_div)) + return -EINVAL; + + if (filter_osr <=3D ADS112C14_DATA_RATE_CFG_FLTR_OSR_1024) + return ads112c14_sinc_latency_tmod[filter_osr][speed_mode]; + + if (filter_osr =3D=3D ADS112C14_DATA_RATE_CFG_FLTR_OSR_25SPS) + return ads112c14_fir_latency_tmod[0][speed_mode]; + + if (filter_osr =3D=3D ADS112C14_DATA_RATE_CFG_FLTR_OSR_20SPS) + return ads112c14_fir_latency_tmod[1][speed_mode]; + + return -EINVAL; +} + +static int ads112c14_get_settling_time_us(struct ads112c14_data *data, + struct ads112c14_channel_state *channel_state, + u8 delay, u32 *settling_time_us) +{ + int fmod_Hz, latency_tmod; + u64 total_tmod; + + fmod_Hz =3D ads112c14_get_fmod_Hz(data, channel_state); + if (fmod_Hz <=3D 0) + return -EINVAL; + + latency_tmod =3D ads112c14_get_latency_tmod(channel_state); + if (latency_tmod < 0) + return latency_tmod; + + total_tmod =3D latency_tmod + ads112c14_delay_to_tmod(delay); + *settling_time_us =3D div64_u64(total_tmod * USEC_PER_SEC, fmod_Hz); + + return 0; +} + +static int ads112c14_find_delay_for_settling_time_us(struct ads112c14_data= *data, + struct ads112c14_channel_state *channel_state, + s64 settling_time_us, u8 *delay) +{ + u32 fixed_latency_us, delay_us; + u64 delay_tmod_needed; + int ret, fmod_Hz; + u8 i; + + ret =3D ads112c14_get_settling_time_us(data, channel_state, 0, &fixed_lat= ency_us); + if (ret) + return ret; + + if (settling_time_us <=3D fixed_latency_us) { + *delay =3D 0; + return 0; + } + + fmod_Hz =3D ads112c14_get_fmod_Hz(data, channel_state); + if (fmod_Hz <=3D 0) + return -EINVAL; + + delay_us =3D settling_time_us - fixed_latency_us; + delay_tmod_needed =3D DIV_ROUND_UP_ULL((u64)delay_us * fmod_Hz, + USEC_PER_SEC); + + for (i =3D 1; i < ADS112C14_DELAY_MAX; i++) { + if (ads112c14_delay_to_tmod(i) >=3D delay_tmod_needed) + break; + } + + *delay =3D i; + + return 0; +} + +static ssize_t ads112c14_read_settling_time(struct iio_dev *indio_dev, + uintptr_t private, + const struct iio_chan_spec *chan, + char *buf) +{ + struct ads112c14_data *data =3D iio_priv(indio_dev); + struct ads112c14_channel_state *channel_state; + u32 settling_time_us; + int vals[2]; + int ret; + + guard(mutex)(&data->lock); + + channel_state =3D &data->channel_states[chan->scan_index]; + + ret =3D ads112c14_get_settling_time_us(data, channel_state, + channel_state->delay, + &settling_time_us); + if (ret) + return ret; + + iio_val_s64_decompose(settling_time_us, &vals[0], &vals[1]); + + return iio_format_value(buf, IIO_VAL_DECIMAL64_MICRO, ARRAY_SIZE(vals), v= als); +} + +static ssize_t ads112c14_write_settling_time(struct iio_dev *indio_dev, + uintptr_t private, + const struct iio_chan_spec *chan, + const char *buf, size_t len) +{ + struct ads112c14_data *data =3D iio_priv(indio_dev); + struct ads112c14_channel_state *channel_state; + s64 settling_time_us; + int integer; + int fract; + u8 delay; + int ret; + + ret =3D iio_str_to_fixpoint(buf, 100000, &integer, &fract); + if (ret) + return ret; + + settling_time_us =3D integer * MICRO + fract; + if (settling_time_us < 0) + return -EINVAL; + + IIO_DEV_ACQUIRE_DIRECT_MODE(indio_dev, claim); + if (IIO_DEV_ACQUIRE_FAILED(claim)) + return -EBUSY; + + guard(mutex)(&data->lock); + + channel_state =3D &data->channel_states[chan->scan_index]; + + ret =3D ads112c14_find_delay_for_settling_time_us(data, channel_state, + settling_time_us, &delay); + if (ret) + return ret; + + channel_state->delay =3D delay; + + return len; +} + +static ssize_t ads112c14_read_settling_time_available(struct iio_dev *indi= o_dev, + uintptr_t private, + const struct iio_chan_spec *chan, + char *buf) +{ + struct ads112c14_data *data =3D iio_priv(indio_dev); + struct ads112c14_channel_state *channel_state; + u8 filter_osr, speed_mode; + const int (*range)[2]; + size_t len =3D 0; + int i; + + guard(mutex)(&data->lock); + + channel_state =3D &data->channel_states[chan->scan_index]; + + filter_osr =3D channel_state->filter_osr; + speed_mode =3D channel_state->speed_mode; + + if (speed_mode >=3D ARRAY_SIZE(ads112c14_fmod_div)) + return -EINVAL; + + if (filter_osr <=3D ADS112C14_DATA_RATE_CFG_FLTR_OSR_1024) + range =3D data->sinc_settling_time_range_available[filter_osr][speed_mod= e]; + else if (filter_osr =3D=3D ADS112C14_DATA_RATE_CFG_FLTR_OSR_25SPS) + range =3D data->fir_settling_time_range_available[0][speed_mode]; + else if (filter_osr =3D=3D ADS112C14_DATA_RATE_CFG_FLTR_OSR_20SPS) + range =3D data->fir_settling_time_range_available[1][speed_mode]; + else + return -EINVAL; + + len +=3D sysfs_emit_at(buf, len, "["); + for (i =3D 0; i < 3; i++) { + s64 range_val; + s32 int_val, rem; + + range_val =3D iio_val_s64_compose(range[i][0], range[i][1]); + int_val =3D div_s64_rem(range_val, MICRO, &rem); + + if (i) + len +=3D sysfs_emit_at(buf, len, " "); + + len +=3D sysfs_emit_at(buf, len, "%d.%06d", int_val, rem); + } + len +=3D sysfs_emit_at(buf, len, "]\n"); + + return len; +} + static int ads112c14_prepare_measurement_channel(struct ads112c14_data *da= ta, const struct iio_chan_spec *chan, bool en_burnout) @@ -636,8 +862,11 @@ static int ads112c14_prepare_measurement_channel(struc= t ads112c14_data *data, return ret; =20 ret =3D regmap_update_bits(data->regmap, ADS112C14_REG_DATA_RATE_CFG, + ADS112C14_DATA_RATE_CFG_DELAY | ADS112C14_DATA_RATE_CFG_GC_EN | ADS112C14_DATA_RATE_CFG_FLTR_OSR, + FIELD_PREP(ADS112C14_DATA_RATE_CFG_DELAY, + channel_state->delay) | FIELD_PREP(ADS112C14_DATA_RATE_CFG_GC_EN, measurement->global_chop && !en_burnout) | FIELD_PREP(ADS112C14_DATA_RATE_CFG_FLTR_OSR, @@ -724,8 +953,11 @@ static int ads112c14_prepare_sys_mon_channel(struct ad= s112c14_data *data, return ret; =20 ret =3D regmap_update_bits(data->regmap, ADS112C14_REG_DATA_RATE_CFG, + ADS112C14_DATA_RATE_CFG_DELAY | ADS112C14_DATA_RATE_CFG_GC_EN | ADS112C14_DATA_RATE_CFG_FLTR_OSR, + FIELD_PREP(ADS112C14_DATA_RATE_CFG_DELAY, + channel_state->delay) | FIELD_PREP(ADS112C14_DATA_RATE_CFG_GC_EN, 0) | FIELD_PREP(ADS112C14_DATA_RATE_CFG_FLTR_OSR, channel_state->filter_osr)); @@ -784,7 +1016,8 @@ static int ads112c14_scan_read(struct ads112c14_data *= data, u8 *buf) return 0; } =20 -static int ads112c14_wait_for_conversion_irq(struct ads112c14_data *data) +static int ads112c14_wait_for_conversion_irq(struct ads112c14_data *data, + u32 settle_time_us) { unsigned long remaining; int ret; @@ -796,13 +1029,16 @@ static int ads112c14_wait_for_conversion_irq(struct = ads112c14_data *data) if (ret) return ret; =20 + /* Give it 1ms more than calculated settling time. */ remaining =3D wait_for_completion_timeout(&data->drdy_completion, - msecs_to_jiffies(100)); + usecs_to_jiffies(settle_time_us + + 1 * USEC_PER_MSEC)); =20 return remaining ? 0 : -ETIMEDOUT; } =20 -static int ads112c14_wait_for_conversion_poll(struct ads112c14_data *data) +static int ads112c14_wait_for_conversion_poll(struct ads112c14_data *data, + u32 settle_time_us) { u32 reg_val; int ret; @@ -812,10 +1048,12 @@ static int ads112c14_wait_for_conversion_poll(struct= ads112c14_data *data) if (ret) return ret; =20 + /* Give it 1ms more than calculated settling time. */ return regmap_read_poll_timeout(data->regmap, ADS112C14_REG_STATUS_MSB, reg_val, FIELD_GET(ADS112C14_STATUS_MSB_DRDY, reg_val), - 1 * USEC_PER_MSEC, 100 * USEC_PER_MSEC); + 1 * USEC_PER_MSEC, settle_time_us + + 1 * USEC_PER_MSEC); } =20 static int ads112c14_single_conversion(struct ads112c14_data *data, @@ -823,6 +1061,8 @@ static int ads112c14_single_conversion(struct ads112c1= 4_data *data, u8 *buf, bool en_burnout, bool for_scan) { struct i2c_client *client =3D to_i2c_client(regmap_get_device(data->regma= p)); + struct ads112c14_channel_state *channel_state; + u32 settle_time_us; int ret; =20 guard(mutex)(&data->lock); @@ -831,10 +1071,26 @@ static int ads112c14_single_conversion(struct ads112= c14_data *data, if (ret) return ret; =20 + channel_state =3D &data->channel_states[chan->scan_index]; + ret =3D ads112c14_get_settling_time_us(data, channel_state, + channel_state->delay, + &settle_time_us); + if (ret) + return ret; + + ret =3D regmap_test_bits(data->regmap, ADS112C14_REG_DATA_RATE_CFG, + ADS112C14_DATA_RATE_CFG_GC_EN); + if (ret < 0) + return ret; + + /* Input chopping doubles the settling time. */ + if (ret) + settle_time_us *=3D 2; + if (data->drdy_irq) - ret =3D ads112c14_wait_for_conversion_irq(data); + ret =3D ads112c14_wait_for_conversion_irq(data, settle_time_us); else - ret =3D ads112c14_wait_for_conversion_poll(data); + ret =3D ads112c14_wait_for_conversion_poll(data, settle_time_us); if (ret) return ret; =20 @@ -1585,6 +1841,17 @@ static const struct iio_enum ads112c14_filter_type_e= num =3D { }; =20 static const struct iio_chan_spec_ext_info ads112c14_ext_info[] =3D { + { + .name =3D "settlingtime", + .read =3D ads112c14_read_settling_time, + .write =3D ads112c14_write_settling_time, + .shared =3D IIO_SEPARATE, + }, + { + .name =3D "settlingtime_available", + .read =3D ads112c14_read_settling_time_available, + .shared =3D IIO_SEPARATE, + }, IIO_ENUM("filter_type", IIO_SEPARATE, &ads112c14_filter_type_enum), IIO_ENUM_AVAILABLE("filter_type", IIO_SEPARATE, &ads112c14_filter_type_en= um), { } @@ -1595,6 +1862,17 @@ static const struct iio_chan_spec_ext_info ads112c14= _ext_info_burnout[] =3D { .name =3D "burnoutraw", .read =3D ads112c14_read_burnout_raw, }, + { + .name =3D "settlingtime", + .read =3D ads112c14_read_settling_time, + .write =3D ads112c14_write_settling_time, + .shared =3D IIO_SEPARATE, + }, + { + .name =3D "settlingtime_available", + .read =3D ads112c14_read_settling_time_available, + .shared =3D IIO_SEPARATE, + }, IIO_ENUM("filter_type", IIO_SEPARATE, &ads112c14_filter_type_enum), IIO_ENUM_AVAILABLE("filter_type", IIO_SEPARATE, &ads112c14_filter_type_en= um), { } @@ -1941,6 +2219,52 @@ static void ads112c14_populate_odr_tables(struct ads= 112c14_data *data) available[0] =3D div_u64_rem(odr_uHz, MICRO, &available[1]); } =20 +static void ads112c14_populate_settling_range_tables(struct ads112c14_data= *data) +{ + s32 (*avail)[2]; + u32 i, j; + + for (i =3D 0; i < ARRAY_SIZE(ads112c14_sinc_latency_tmod); i++) { + for (j =3D 0; j < ARRAY_SIZE(ads112c14_fmod_div); j++) { + u64 fmod_Hz =3D data->fclk_Hz / ads112c14_fmod_div[j]; + u64 start_tmod =3D ads112c14_sinc_latency_tmod[i][j]; + u64 step_tmod =3D ads112c14_delay_to_tmod(1); + u64 stop_tmod =3D start_tmod + ads112c14_delay_to_tmod(ADS112C14_DELAY_= MAX); + s64 start_us, step_us, stop_us; + + start_us =3D DIV_ROUND_CLOSEST_ULL(start_tmod * USEC_PER_SEC, fmod_Hz); + step_us =3D DIV_ROUND_CLOSEST_ULL(step_tmod * USEC_PER_SEC, fmod_Hz); + stop_us =3D DIV_ROUND_CLOSEST_ULL(stop_tmod * USEC_PER_SEC, fmod_Hz); + + avail =3D data->sinc_settling_time_range_available[i][j]; + + iio_val_s64_decompose(start_us, &avail[0][0], &avail[0][1]); + iio_val_s64_decompose(step_us, &avail[1][0], &avail[1][1]); + iio_val_s64_decompose(stop_us, &avail[2][0], &avail[2][1]); + } + } + + for (i =3D 0; i < ARRAY_SIZE(ads112c14_fir_latency_tmod); i++) { + for (j =3D 0; j < ARRAY_SIZE(ads112c14_fmod_div); j++) { + u64 fmod_Hz =3D data->fclk_Hz / ads112c14_fmod_div[j]; + u64 start_tmod =3D ads112c14_fir_latency_tmod[i][j]; + u64 step_tmod =3D ads112c14_delay_to_tmod(1); + u64 stop_tmod =3D start_tmod + ads112c14_delay_to_tmod(ADS112C14_DELAY_= MAX); + s64 start_us, step_us, stop_us; + + start_us =3D DIV_ROUND_CLOSEST_ULL(start_tmod * USEC_PER_SEC, fmod_Hz); + step_us =3D DIV_ROUND_CLOSEST_ULL(step_tmod * USEC_PER_SEC, fmod_Hz); + stop_us =3D DIV_ROUND_CLOSEST_ULL(stop_tmod * USEC_PER_SEC, fmod_Hz); + + avail =3D data->fir_settling_time_range_available[i][j]; + + iio_val_s64_decompose(start_us, &avail[0][0], &avail[0][1]); + iio_val_s64_decompose(step_us, &avail[1][0], &avail[1][1]); + iio_val_s64_decompose(stop_us, &avail[2][0], &avail[2][1]); + } + } +} + static void ads112c14_populate_tables(struct ads112c14_data *data) { u32 full_scale, fsr_bits; @@ -1979,6 +2303,7 @@ static void ads112c14_populate_tables(struct ads112c1= 4_data *data) ads112c14_populate_scale_available(data->sys_mon_chan_short_scale_availab= le, full_scale, fsr_bits); ads112c14_populate_odr_tables(data); + ads112c14_populate_settling_range_tables(data); } =20 static int ads112c14_probe(struct i2c_client *client) --=20 2.43.0 From nobody Tue Sep 29 11:58:32 2026 Received: from mail-oo1-f53.google.com (mail-oo1-f53.google.com [209.85.161.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 98FF122A817 for ; Sat, 8 Aug 2026 00:20:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.161.53 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786148443; cv=none; b=jpcfkngrIQ+/aoS7g+K3KzEZmDuYgcJjUkWEooiRAlTmN1z35iQ5rp40dGnb/AUV0kR+oWlh5eN1cWrz+pPApmIKUHzEE7U/umCK4T0CNxNTXActUnVgUICfr4FxF2iHob3E7uyLigPHTLDMxMxbLuCqCFT2De+xIV0XeH0EiU4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786148443; c=relaxed/simple; bh=6QmljWoox6zrX2xlqNFzdFk9xTwBnbgWKPt4zs2E6Zg=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=NkJMfn1vNDc8o1LLWjlEhWmmxHHdvvwUTSuj1cETFEL8UxMfdfpnhwidQsBwJzmNJteh82EoXdt61up7xfSoo4LVBHQrHWEDtqwwJEAC+3DZpQOPO98RrrCBcF4AcNZD0PMRHasMyhAv16K8sFmsCBV993iEx1QMOT6vDp4wnZ4= 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 header.i=@baylibre.com header.b=ZCT/Afcf; arc=none smtp.client-ip=209.85.161.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 header.i=@baylibre.com header.b="ZCT/Afcf" Received: by mail-oo1-f53.google.com with SMTP id 006d021491bc7-6aec68b03e2so19146eaf.3 for ; Fri, 07 Aug 2026 17:20:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre.com; s=google; t=1786148440; x=1786753240; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=lsOi57ifL3TPKpC/47o26x/a2mJaTtoHuDckWfzu3ZY=; b=ZCT/AfcfJLG+ACHMapKLXmhMHzPEYT5939xyvklcuW03ZGd5BV3NlVPq33dq1orlmw asBWAQPTsKL5zRdFOU8khtvOw068fndj0EY672JsjH6MIsQVw2/vgsbeeIkyLHAXD67z iFDY8uB7F1+4NFkU2XMr+ns+JKnXGu5merJivy+Jbsrzq6sFFkd4zW3EMzQd1pyhnnXO ibgNwOp0DxlTL7ia4T4blG6RPusJ3POLpks9XGu0tOugthx91N9uSKN1McMJsSScXg3O kvxZnNiqHwmVEoa/UJ8l3jMXKdPeMt9HNLWErwrhedRanrr2L24Jic+XJZbH43oSfrhC KsiA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1786148440; x=1786753240; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=lsOi57ifL3TPKpC/47o26x/a2mJaTtoHuDckWfzu3ZY=; b=fha9FaegeqI7pVmsRGP9LklNiKPNIPqyluMhAzag86cWLouALH59qHOIUqFC2yHJ0w W9eyD1mNaAQEQPiNrZXjbWKhuMmXix3A9kD3Y1lmWxfMuGat1Qh5QCzAas/eXbbtLOY+ n3bnhVRAvqN92IcuB3fVb9N/JFUj51us2ERzcHorM3cvEsQwEfckPQX/Xkos/BHn0Oj+ i2hKOZihnNRwazHV13vaNtrURrUaDfiY6eofyP85Qt5tXNHX0Jhq8jszxtTt8HyKzwUK QdmkXWlr5vMPQrD4bqjYpc/j9xUq4LQYTGVQMPUDddxIcom6vsSWYY66nmUiTx9FVONO 5EgA== X-Forwarded-Encrypted: i=1; AHgh+Rpm9hJc9sKRy1ia1IilW5GzmahN2dVN23Iuxy71tlfBnNe8f3b5To0XSplChJs3h0TRgMLS+V8F12eWbC0=@vger.kernel.org X-Gm-Message-State: AOJu0YzFTYhHlW1wH4/joeUOTSH/5rCV/vNOtIzH1gteS6xyVY2wEa7X xQjx0FAfsAtEgbUeVFHqMdbIfcQBXcihhV6Yf0WcBScAiI2BNoYwdRMfpiULKhB0XcOzjXXnR6k IbgUpzy0= X-Gm-Gg: AR+sD10WqnKnBa7W1sVv6FJ4nbkqUekvmnpmLfsIqAnkIX20FV+NDu8O6iRMpWFTO86 E2Jy6RTKgcuVoGd/lWzS/1n7Cn8EU8zLqaZaLwFaKfkvmpuCBsGXrYv33YHon1I/GGctlOBrVFG onsgwDWqpujYvsQ5ehqIhgz/pPH0vr2vRrausmSbhp3PQ/LmHV8YOlic/zM1sar8kWnO93J45zU d3pxI49I9lU6dDCQjFpjtycfYNH37tMqgUqfL5WJQcr9T6k2DsWRlgBPitg8dTBcLiWyY4SWf5m EGhmfJafw71Ri/1vI9zcFs3XyJM9noarxAJ/KTGJgTkQ77eVAmJeND26KNk+JI4bgBMS2VPxJL4 FrgyiMysyBCq/EWJ2Fii4IsmK07q91j7DdexmEmjl11mfnUkEar7Wm5qZptKL4wHpbFhdDX0txO ZrlVMPqs8XyaMOeoYCx25zGieR6RaNk7bV7CZXInAqo1XPbJy1xdgm/b5Ln1Jqdm5l X-Received: by 2002:a05:6820:c0d2:10b0:6ae:9712:cad0 with SMTP id 006d021491bc7-6ae9713173amr10479429eaf.21.1786148440488; Fri, 07 Aug 2026 17:20:40 -0700 (PDT) Received: from [127.0.1.1] ([2600:8803:e7e4:500:b714:88c:313d:dee2]) by smtp.gmail.com with ESMTPSA id 46e09a7af769-7f35b5a7616sm2526147a34.8.2026.08.07.17.20.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 07 Aug 2026 17:20:40 -0700 (PDT) From: "David Lechner (TI)" Date: Fri, 07 Aug 2026 19:19:50 -0500 Subject: [PATCH 5/5] iio: ABI: add settlingtime attributes 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: <20260807-iio-adc-ti-ads112c14-filter-support-v1-5-4d3ba00caf18@baylibre.com> References: <20260807-iio-adc-ti-ads112c14-filter-support-v1-0-4d3ba00caf18@baylibre.com> In-Reply-To: <20260807-iio-adc-ti-ads112c14-filter-support-v1-0-4d3ba00caf18@baylibre.com> To: Jonathan Cameron , =?utf-8?q?Nuno_S=C3=A1?= , Andy Shevchenko Cc: linux-iio@vger.kernel.org, linux-kernel@vger.kernel.org, "David Lechner (TI)" X-Mailer: b4 0.17-dev X-Developer-Signature: v=1; a=openpgp-sha256; l=2498; i=dlechner@baylibre.com; h=from:subject:message-id; bh=6QmljWoox6zrX2xlqNFzdFk9xTwBnbgWKPt4zs2E6Zg=; b=owEBbQGS/pANAwAKAcLMIAH/AY/AAcsmYgBqdnZJWRtURGKYc9u2fepn88ujSjHgxoLOtyJqP sAnHP95ob2JATMEAAEKAB0WIQTsGNmeYg6D1pzYaJjCzCAB/wGPwAUCanZ2SQAKCRDCzCAB/wGP wCu9CACB/BO+XSv6PpDzfkZfplTz//bJI1ElN3QkP+s2SUloGnMGmbo2AJO/6h6TBWrttzL/6zz RJLZLTHT9aW74CCDGUWJkO4JWiJ2qvqiZts7lVedg4k2rRfwv57HQpwJUf0ieZwE429KzgWUbbn NTjx9h4C4Tp3MTR+53dIhN8AZg7OLN89UsFPOGUBwx09h7Z6qXYMrN8xF9ZyBHYUh+aihQLlPVK YNQSvlCw+QR3GAUgo9pQe/U7nZmMtS0qcQMdBgN7PszXhrv+l/MEbSCVIayhBrM4CNzdN9py1XZ t8e9F6T4N2KgbAoOkzY62sAnMs39oC2ql3ryr8vEqUd4TDOB X-Developer-Key: i=dlechner@baylibre.com; a=openpgp; fpr=8A73D82A6A1F509907F373881F8AF88C82F77C03 Add new generic attributes for input settling time introduced in the ti-ads122c14 driver. Usually, in IIO the output data rate is 1 / sampling_frequency. There are known devices (generally ones with filtering and oversampling) where the first conversion takes longer than 1 / sampling_frequency to allow the input to settle in order to have a valid conversion result. Then, any subsequent conversions in a continuous sampling mode would be done at the regular interval defined by 1 / sampling_frequency. This attribute is intended to allow controlling that settling time duration. A device that has input chopping enabled would see this settling time on every conversion since the device setting (i.e. the input mux) changes on every conversion. Signed-off-by: David Lechner (TI) --- Documentation/ABI/testing/sysfs-bus-iio | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/te= sting/sysfs-bus-iio index a8e1cb8e7490..344f5296a9cc 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio +++ b/Documentation/ABI/testing/sysfs-bus-iio @@ -2402,6 +2402,27 @@ Description: Specifies which filter type apply to the channel. The possible values are given by the filter_type_available attribute. =20 +What: /sys/bus/iio/devices/iio:deviceX/in_resistanceY_settlingtime +What: /sys/bus/iio/devices/iio:deviceX/in_tempY_settlingtime +What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_settlingtime +What: /sys/bus/iio/devices/iio:deviceX/in_voltageY-voltageZ_settlingtime +KernelVersion: 7.3 +Contact: linux-iio@vger.kernel.org +Description: + Set/read total settling time in seconds for a device to settle + after starting the first conversion after any settings have + changed. The data for the conversion is outputted at the end of + this time. + +What: /sys/bus/iio/devices/iio:deviceX/in_resistanceY_settlingtime_availa= ble +What: /sys/bus/iio/devices/iio:deviceX/in_tempY_settlingtime_available +What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_settlingtime_available +What: /sys/bus/iio/devices/iio:deviceX/in_voltageY-voltageZ_settlingtime_= available +KernelVersion: 7.3 +Contact: linux-iio@vger.kernel.org +Description: + Available settlingtime values in IIO range or list format. + What: /sys/.../events/in_proximity_thresh_either_runningperiod KernelVersion: 6.6 Contact: linux-iio@vger.kernel.org --=20 2.43.0