From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.remote-ip=209.85.217.54 ARC-Seal: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; cv=none; t=1792883655; b=HOpisJyLjTMYofxpVf/eeMBgP/XtZIRNiwCUU7ZVgji+YcoztZQGIasqZm/FFyCZoTgs jMi1bdzzUhrdtbCoxdBsIAkZDIwF6+cubSf1S4TvkT1PpJ3QGxK9D9rkWmcNrx6mYYMzb f9bQAKm2/xkTjxNjQVyqqh6OlpuLNzHOyJIm5ZYcBl1OyiRRPtj+xjDbbhqCNDkTYbUAX vwNdQcLkNgfdJ9jsHOTr3McJMWYbNss4tMJEelR3qc+SGva8pBLCFQQYWTr6Zq0JpJj0n HvXqFuY2X8itKGDoDBQ+i3oag1mgG+X8i+MgcXMyK7SnUa8LK1p0j1/kM7XC818XnoA== ARC-Message-Signature: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; c=relaxed/relaxed; t=1792883655; h=DMARC-Filter:Received:DKIM-Signature:X-Google-DKIM-Signature: X-Forwarded-Encrypted:X-Gm-Message-State:X-Gm-Gg:X-Received:Received: From:To:Cc:Subject:Date:Message-ID:X-Mailer:In-Reply-To:References: MIME-Version:Content-Transfer-Encoding; bh=VU+PRp8E+r2gsR8UrQr9iiFb4OtLPockRgEmkyRdn3I=; b=gPL5rorMJgmHO5sgxk2nuLfpOuXe2tYhx8RhQPXScE0V7bAo7guHRs4Z+etGEueoCiVA II+PTKdB+l63uPdDDjsSPiRFxe/0qdJyiUTWoEcDJXzcZ3pXvJ6rxxezOstK8XY45oa0a Aommhstwz2FGZmPSVmcBTZuYJ/WONQM1el0g7CS1bJRAmgrfwF21Jm/kTdnRBmyZTHCoJ tq1xQFgmwAhD5Nj2FeHxvGutXNkZ1UqgOlDZhj6BJfTVOsWk6Sx38mGJWs/Y48s29kW0U gnm2WfE47JXopd6WQ6GCLXr9sKt+NnEtqZeMu1mowN6H6/ls25Wb+zhOMa1lmEbZWDg== ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20251104 header.b=AzulYp8A; arc=none smtp.remote-ip=209.85.217.54 Received: from mail-vs1-f54.google.com (mail-vs1-f54.google.com [209.85.217.54]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits) key-exchange X25519 server-signature ECDSA (prime256v1) server-digest SHA256) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 73220606A31F for ; Sat, 24 Oct 2026 23:14:15 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.2 smtp.subspace.kernel.org 73220606A31F Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key, unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20251104 header.b=AzulYp8A Received: by mail-vs1-f54.google.com with SMTP id ada2fe7eead31-7ce645a1c6aso366746137.3 for ; Sat, 24 Oct 2026 16:14:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1792883654; x=1793488454; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=VU+PRp8E+r2gsR8UrQr9iiFb4OtLPockRgEmkyRdn3I=; b=AzulYp8A6Wf4nq2XC3cgt7egA1O5t+FvdyeSEIPOQ/iCpA2qpwFd6eDvKS/aOJXwCz YxGxRAo/eHgxNUup5cGm8DUpSPcLByz4pFkFhz0gF7wblBXS5PbmpCV2Uz93vX4JLfTk 6hqywKbyWbj3JXiBUZptGNZukRZnHzDaArkJ2lG+x14dh62dACZVCUepQF84AelBv9p8 F+9HBYRYXaoE8cJS58EdXWEInxan97mX0o/habkhjhSJmKbig10bUSBGyBNxXUPAr5TQ 1uTaK2vrxBOhcC+QitH5YbDGZ3kv8EXHkKeUJmGLrJPrO8sJUovkImghvVEUnG9+s5Xg /XRQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792883654; x=1793488454; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=VU+PRp8E+r2gsR8UrQr9iiFb4OtLPockRgEmkyRdn3I=; b=yhHjrveIT1g/RIaku2j5LDaN1tbeCsl366VsFdwEd3AegaIHILS/y0JVlYlos8IBf7 VIwjsBZkgCayzDKx+yI/hfsc2cB+QX7TTska6y9NqJ+Rof0RATThICDPs6FXinSFGVe5 cxS2YQXwqBplM6cjcc/kWCqlQK7OP5dya04ERnxN9rCDVMRM9Nx0i36VwXWr66ZfN6g0 Ns1Ibl97f6zAc4a5yfDKuu/ry4GkEJNr0qBPBSz4dGXo0XxMkjynKkq4Q4/DcT4daEgx rpZydoHXz5JK5Xa/zJEjythiVZAugr8+KFWIRIQr0c9SEGfnDwGImi1FzXb2Yi9XmcVP 44jA== X-Forwarded-Encrypted: i=1; AKwUvBzRlo/+LAPKhdOZwTtAflMVmBt2r9dOC1KFfhgT1tH/Sw9rgvkvrJu/jtvDe076tUKrkzQJgmIbKz16@vger.kernel.org X-Gm-Message-State: AFq9FYIFoIyMnkLS9hRUtJ7RCPmDYKLS4CKjkMjXiNewexNNsmsHrAqU kpgxh02+5cBndKxnY+BW7mZ2x7b+H4NUr7pmGm964KvfVex/Wino3EoB X-Gm-Gg: AYBFou0PNLeFD5ojJ/Ywrd4f1IyIDcGt0I/+UMKOwjRKNpKfrW13u0CDcKDxW5Bg8jt Ef6EH0d7WJsqFzXS37QQrO6U9LQ+m/MUza97/ULAy1DOElT3Eylx4DOPkx4q+Dm7bGubBk4ZcqI pnj34bfIxsfO7TlI0J/8a0qB9jfUToliH3sV9W8+CEI5SHBh2UXlDMf7VEHB1iEJb7XNViudI27 DDC0nufSHWuDiwsHjMTprGTtomy+aUz+vGR1UZdFHj8EIhEMHRzKODezIF7PiKbpg1MTaojz82A Nth1OeW1cYSm9FxFGV2ZwrpiOl1SZMb21Qu8qwtGPvH3qwWwIFHBiW+C0X+EF+JIwjbkz65ySyI Vn2MKvw5bUnjt33yJqU0C9yYVCDNNdUIeovMbcSKYlAUW0gVfwwpEWltN/wE+S2Rqyuztu7E+7N Qnv/CInXNCYamGAV3HL3t5Nopgvd0tt92uJdS1+K+CNOGQCIwAe3l2yqUfn79CfTqHBobCnsTA3 d6h09CI526TWFUXLUJMwxMAz8bPuPgqyjKqjuSs6KKCK7BMjdxWAcOS08BvyvG6Q/m3M640sNcg rrC3 X-Received: by 2002:a05:6102:809e:b0:7c3:1898:e8e2 with SMTP id ada2fe7eead31-7ce5ccc3247mr1067852137.13.1792883654381; Sat, 24 Oct 2026 16:14:14 -0700 (PDT) Received: from stephan-Inspiron-15-3520.. ([2804:5d20:6009:6701:efc9:520c:e99d:e5ce]) by smtp.gmail.com with ESMTPSA id a1e0cc1a2514c-9910e7b8f0csm3775406241.5.2026.10.24.16.14.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 24 Oct 2026 16:14:13 -0700 (PDT) From: Stephan Costa Barros To: Jonathan Cameron Cc: David Lechner , =?UTF-8?q?Nuno=20S=C3=A1?= , Andy Shevchenko , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Mike Looijmans , Andy Shevchenko , =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= , Krzysztof Kozlowski , linux-iio@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v2 4/6] iio: adc: ti-ads1298: prepare for more chip families Date: Sat, 24 Oct 2026 20:13:33 -0300 Message-ID: <20261024231335.280955-5-stephanbrrs8@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20261024231335.280955-1-stephanbrrs8@gmail.com> References: <20261024231335.280955-1-stephanbrrs8@gmail.com> X-Mailing-List: devicetree@vger.kernel.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Transfer-Encoding: 8bit The ADS1299 has the register map of the ADS129x, with other gains, data rates, reference and ID layout. To support it in this driver, collect what differs between families in a chip info structure, given as match data. The private structure has carried an unused chip_info pointer since the driver was added. The chip info holds: - the regmap configuration and the PGA gain table; - the data rate rules: the base shift, whether CONFIG1 has an HR bit, and the oversampling ratio at DR = 0; - the internal reference, whether CONFIG3 has the VREF_4V bit, and the reserved bits of CONFIG3 that must be written as 1; - a callback that checks the ID register and sets the channel count and the name, as the ID layouts differ; bit 3 alone tells them apart. No functional change. Signed-off-by: Stephan Costa Barros --- drivers/iio/adc/ti-ads1298.c | 132 +++++++++++++++++++++++++---------- 1 file changed, 96 insertions(+), 36 deletions(-) diff --git a/drivers/iio/adc/ti-ads1298.c b/drivers/iio/adc/ti-ads1298.c index b390c13ae..5ad543bdf 100644 --- a/drivers/iio/adc/ti-ads1298.c +++ b/drivers/iio/adc/ti-ads1298.c @@ -49,8 +49,6 @@ #define ADS1298_REG_CONFIG1 0x01 #define ADS1298_MASK_CONFIG1_HR BIT(7) #define ADS1298_MASK_CONFIG1_DR GENMASK(2, 0) -#define ADS1298_SHIFT_DR_HR 6 -#define ADS1298_SHIFT_DR_LP 7 #define ADS1298_LOWEST_DR 0x06 #define ADS1298_REG_CONFIG2 0x02 @@ -66,6 +64,7 @@ #define ADS1298_MASK_CONFIG3_PWR_REFBUF BIT(7) #define ADS1298_MASK_CONFIG3_RESERVED BIT(6) #define ADS1298_MASK_CONFIG3_VREF_4V BIT(5) +#define ADS1298_VREF_4V_MV 4000 #define ADS1298_REG_LOFF 0x04 #define ADS1298_REG_CHnSET(n) (0x05 + (n)) @@ -105,6 +104,31 @@ #define ADS1298_SPI_RDATA_BUFFER_SIZE_MAX \ ADS1298_SPI_RDATA_BUFFER_SIZE(ADS1298_MAX_CHANNELS) +/* What differs between the chip families the driver supports */ +struct ads1298_chip_info { + /* Checks the ID register, and sets the channel count and the name */ + int (*parse_id)(struct iio_dev *indio_dev, unsigned int id); + const struct regmap_config *regmap_config; + /* PGA gain for each value of the GAIN field of CHnSET */ + const u8 *gains; + unsigned int num_gains; + /* + * The data rate is f_CLK >> (dr_shift + DR). With an HR bit in + * CONFIG1, dr_shift is that of the high-resolution mode, and the + * low-power mode shifts one more. + */ + unsigned int dr_shift; + bool has_hr; + /* Oversampling ratio at DR = 0 */ + unsigned int osr_base; + /* Internal reference, in millivolts */ + unsigned int vref_mv; + /* CONFIG3 has the VREF_4V bit, which selects a 4 V internal reference */ + bool has_vref_4v; + /* Reserved bits of CONFIG3 that must be written as 1 */ + unsigned int config3_reserved; +}; + struct ads1298_private { const struct ads1298_chip_info *chip_info; struct spi_device *spi; @@ -286,6 +310,7 @@ static int ads1298_read_one(struct ads1298_private *priv, int chan_index) static int ads1298_get_samp_freq(struct ads1298_private *priv, int *val) { + const struct ads1298_chip_info *info = priv->chip_info; unsigned long rate; unsigned int cfg; int ret; @@ -302,10 +327,10 @@ static int ads1298_get_samp_freq(struct ads1298_private *priv, int *val) return -EINVAL; /* Data rate shift depends on HR/LP mode */ - if (cfg & ADS1298_MASK_CONFIG1_HR) - rate >>= ADS1298_SHIFT_DR_HR; + if (info->has_hr && !(cfg & ADS1298_MASK_CONFIG1_HR)) + rate >>= info->dr_shift + 1; else - rate >>= ADS1298_SHIFT_DR_LP; + rate >>= info->dr_shift; *val = rate >> (cfg & ADS1298_MASK_CONFIG1_DR); @@ -314,6 +339,7 @@ static int ads1298_get_samp_freq(struct ads1298_private *priv, int *val) static int ads1298_set_samp_freq(struct ads1298_private *priv, int val) { + const struct ads1298_chip_info *info = priv->chip_info; unsigned long rate; unsigned int factor; unsigned int cfg; @@ -327,9 +353,9 @@ static int ads1298_set_samp_freq(struct ads1298_private *priv, int val) if (val <= 0) return -EINVAL; - factor = (rate >> ADS1298_SHIFT_DR_HR) / val; - if (factor >= BIT(ADS1298_SHIFT_DR_LP)) - cfg = ADS1298_LOWEST_DR; + factor = (rate >> info->dr_shift) / val; + if (factor >= BIT(ADS1298_LOWEST_DR + 1)) + cfg = ADS1298_LOWEST_DR; /* Lowest rate, in LP mode */ else if (factor) cfg = ADS1298_MASK_CONFIG1_HR | ilog2(factor); /* Use HR mode */ else @@ -340,11 +366,10 @@ static int ads1298_set_samp_freq(struct ads1298_private *priv, int val) cfg); } -static const u8 ads1298_pga_settings[] = { 6, 1, 2, 3, 4, 8, 12 }; - static int ads1298_get_scale(struct ads1298_private *priv, int channel, int *val, int *val2) { + const struct ads1298_chip_info *info = priv->chip_info; unsigned int pga_idx; int ret; unsigned int regval; @@ -356,13 +381,16 @@ static int ads1298_get_scale(struct ads1298_private *priv, return ret; *val = ret / MILLI; /* Convert to millivolts */ - } else { + } else if (info->has_vref_4v) { ret = regmap_read(priv->regmap, ADS1298_REG_CONFIG3, ®val); if (ret) return ret; /* Reference in millivolts */ - *val = regval & ADS1298_MASK_CONFIG3_VREF_4V ? 4000 : 2400; + *val = regval & ADS1298_MASK_CONFIG3_VREF_4V ? + ADS1298_VREF_4V_MV : info->vref_mv; + } else { + *val = info->vref_mv; } ret = regmap_read(priv->regmap, ADS1298_REG_CHnSET(channel), ®val); @@ -370,10 +398,10 @@ static int ads1298_get_scale(struct ads1298_private *priv, return ret; pga_idx = FIELD_GET(ADS1298_MASK_CH_PGA, regval); - if (pga_idx >= ARRAY_SIZE(ads1298_pga_settings)) + if (pga_idx >= info->num_gains) return -EINVAL; - gain = ads1298_pga_settings[pga_idx]; + gain = info->gains[pga_idx]; /* Full scale is VREF / gain, signed, hence the -1 */ *val2 = gain << (ADS1298_BITS_PER_SAMPLE - 1); @@ -414,7 +442,7 @@ static int ads1298_read_raw(struct iio_dev *indio_dev, if (ret) return ret; - *val = 16 << (*val & ADS1298_MASK_CONFIG1_DR); + *val = priv->chip_info->osr_base << (*val & ADS1298_MASK_CONFIG1_DR); return IIO_VAL_INT; default: return -EINVAL; @@ -713,31 +741,20 @@ static const struct regmap_config ads1298_regmap_config = { .cache_type = REGCACHE_MAPLE, }; -static int ads1298_init(struct iio_dev *indio_dev) +static int ads1298_parse_id(struct iio_dev *indio_dev, unsigned int id) { struct ads1298_private *priv = iio_priv(indio_dev); struct device *dev = &priv->spi->dev; const char *suffix; unsigned int nu_ch; - unsigned int val; - int ret; - - /* Device initializes into RDATAC mode, which we don't want */ - ret = ads1298_write_cmd(priv, ADS1298_CMD_SDATAC); - if (ret) - return ret; - - ret = regmap_read(priv->regmap, ADS1298_REG_ID, &val); - if (ret) - return ret; /* Fill in name and channel count based on what the chip told us */ - nu_ch = FIELD_GET(ADS1298_MASK_ID_CHANNELS, val); + nu_ch = FIELD_GET(ADS1298_MASK_ID_CHANNELS, id); /* 0, 1 and 2 are 4, 6 and 8 channels; the other codes are reserved */ if (nu_ch > 2) - return dev_err_probe(dev, -ENODEV, "Unknown ID: 0x%x\n", val); + return dev_err_probe(dev, -ENODEV, "Unknown ID: 0x%x\n", id); indio_dev->num_channels = 4 + 2 * nu_ch; - switch (val & ADS1298_MASK_ID_FAMILY) { + switch (id & ADS1298_MASK_ID_FAMILY) { case ADS1298_ID_FAMILY_ADS129X: suffix = ""; break; @@ -745,19 +762,57 @@ static int ads1298_init(struct iio_dev *indio_dev) suffix = "r"; break; default: - return dev_err_probe(dev, -ENODEV, "Unknown ID: 0x%x\n", val); + return dev_err_probe(dev, -ENODEV, "Unknown ID: 0x%x\n", id); } indio_dev->name = devm_kasprintf(dev, GFP_KERNEL, "ads129%u%s", indio_dev->num_channels, suffix); if (!indio_dev->name) return -ENOMEM; - val = ADS1298_MASK_CONFIG3_RESERVED; /* Must write 1 always */ + return 0; +} + +static const u8 ads1298_gains[] = { 6, 1, 2, 3, 4, 8, 12 }; + +static const struct ads1298_chip_info ads1298_chip_info = { + .parse_id = ads1298_parse_id, + .regmap_config = &ads1298_regmap_config, + .gains = ads1298_gains, + .num_gains = ARRAY_SIZE(ads1298_gains), + .dr_shift = 6, + .has_hr = true, + .osr_base = 16, + .vref_mv = 2400, + .has_vref_4v = true, + .config3_reserved = ADS1298_MASK_CONFIG3_RESERVED, +}; + +static int ads1298_init(struct iio_dev *indio_dev) +{ + struct ads1298_private *priv = iio_priv(indio_dev); + unsigned int val; + int ret; + + /* Device initializes into RDATAC mode, which we don't want */ + ret = ads1298_write_cmd(priv, ADS1298_CMD_SDATAC); + if (ret) + return ret; + + ret = regmap_read(priv->regmap, ADS1298_REG_ID, &val); + if (ret) + return ret; + + ret = priv->chip_info->parse_id(indio_dev, val); + if (ret) + return ret; + + val = priv->chip_info->config3_reserved; /* Must write 1 always */ if (!priv->reg_vref) { /* Enable internal reference */ val |= ADS1298_MASK_CONFIG3_PWR_REFBUF; /* Use 4V VREF when power supply is at least 4.4V */ - if (regulator_get_voltage(priv->reg_avdd) >= 4400000) + if (priv->chip_info->has_vref_4v && + regulator_get_voltage(priv->reg_avdd) >= 4400000) val |= ADS1298_MASK_CONFIG3_VREF_4V; } ret = regmap_write(priv->regmap, ADS1298_REG_CONFIG3, val); @@ -785,6 +840,10 @@ static int ads1298_probe(struct spi_device *spi) priv = iio_priv(indio_dev); + priv->chip_info = spi_get_device_match_data(spi); + if (!priv->chip_info) + return -ENODEV; + /* Reset to be asserted before enabling clock and power */ reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH); if (IS_ERR(reset_gpio)) @@ -836,7 +895,8 @@ static int ads1298_probe(struct spi_device *spi) init_completion(&priv->completion); init_waitqueue_head(&priv->idle_wq); spin_lock_init(&priv->irq_busy_lock); - priv->regmap = devm_regmap_init(dev, NULL, priv, &ads1298_regmap_config); + priv->regmap = devm_regmap_init(dev, NULL, priv, + priv->chip_info->regmap_config); if (IS_ERR(priv->regmap)) return PTR_ERR(priv->regmap); @@ -896,13 +956,13 @@ static int ads1298_probe(struct spi_device *spi) } static const struct spi_device_id ads1298_id[] = { - { .name = "ads1298" }, + { .name = "ads1298", .driver_data = (kernel_ulong_t)&ads1298_chip_info }, { } }; MODULE_DEVICE_TABLE(spi, ads1298_id); static const struct of_device_id ads1298_of_table[] = { - { .compatible = "ti,ads1298" }, + { .compatible = "ti,ads1298", .data = &ads1298_chip_info }, { } }; MODULE_DEVICE_TABLE(of, ads1298_of_table); -- 2.43.0