Re: [PATCH v7 2/2] iio: adc: ti-ads112c04: Add support for TI ADS112C04

Andy Shevchenko <[email protected]>
Newsgroups org.kernel.vger.linux-iio,org.kernel.vger.linux-devicetree,org.kernel.vger.linux-kernel
Organization Intel Finland Oy - BIC 0357606-4 - c/o Alberga Business Park, 6 krs, Bertel Jungin Aukio 5, 02600 Espoo
Message-ID <[email protected]>
On Mon, Aug 24, 2026 at 04:49:39PM +0800, Kyle Hsieh wrote:
> Add IIO driver support for the Texas Instruments ADS112C04 (16-bit)
> delta-sigma ADCs.
> 
> The driver implements:
> - Single-shot conversions using the IIO raw read interface.
> - Dynamic parsing of single-ended and differential channels from
>   device tree child nodes.
> - Hardware interrupt support via the DRDY pin, falling back to
>   software polling if no IRQ is provided.
> - Per-channel reference source selection (internal 2.048V, external
>   REFP/REFN, or AVDD) via the reference-sources device tree property.
>   refn-supply is not yet supported.
> - Hardware reset via the reset controller framework, falling back to
>   the RESET command when no reset controller is present.

FWIW,
Reviewed-by: Andy Shevchenko <[email protected]>

...

> +static int ads112c04_probe(struct i2c_client *client)
> +{
> +	struct device *dev = &client->dev;
> +	struct iio_dev *indio_dev;
> +	struct ads112c04_state *st;
> +	struct reset_control *reset;
> +	bool need_avdd_ref = false, need_ext_ref = false;
> +	int ret;
> +
> +	indio_dev = devm_iio_device_alloc(dev, sizeof(*st));
> +	if (!indio_dev)
> +		return -ENOMEM;
> +
> +	st = iio_priv(indio_dev);
> +	st->client = client;
> +
> +	ret = devm_mutex_init(dev, &st->lock);
> +	if (ret)
> +		return ret;
> +
> +	init_completion(&st->completion);
> +
> +	indio_dev->name = "ads112c04";
> +	indio_dev->modes = INDIO_DIRECT_MODE;
> +	indio_dev->info = &ads112c04_info;
> +
> +	/* Forward compatibility checks for unimplemented DT properties */
> +	if (device_property_present(dev, "refn-supply") ||
> +	    device_property_present(dev, "ti,refp-refn-resistor-ohms"))
> +		return dev_err_probe(dev, -EOPNOTSUPP,
> +				     "refn-supply and external resistors are not supported yet\n");
> +
> +	ret = ads112c04_parse_channels(indio_dev, &need_avdd_ref, &need_ext_ref);
> +	if (ret)
> +		return ret;
> +
> +	if (need_avdd_ref) {
> +		ret = devm_regulator_get_enable_read_voltage(dev, "avdd");
> +		if (ret < 0)
> +			return dev_err_probe(dev, ret, "failed to get avdd voltage\n");
> +
> +		st->avdd_mV = ret / (MICRO / MILLI);
> +	} else {
> +		ret = devm_regulator_get_enable(dev, "avdd");
> +		if (ret)
> +			return dev_err_probe(dev, ret, "failed to get avdd regulator\n");
> +	}
> +
> +	ret = devm_regulator_get_enable(dev, "dvdd");
> +	if (ret)
> +		return dev_err_probe(dev, ret, "failed to get dvdd regulator\n");
> +
> +	if (device_property_present(dev, "refp-supply")) {
> +		ret = devm_regulator_get_enable_read_voltage(dev, "refp");
> +		if (ret < 0)
> +			return dev_err_probe(dev, ret, "failed to get refp voltage\n");
> +
> +		st->ext_ref_mV = ret / (MICRO / MILLI);
> +	}
> +
> +	if (need_ext_ref && !st->ext_ref_mV)
> +		return dev_err_probe(dev, -EINVAL,
> +				     "external reference measurements require refp-supply\n");
> +
> +	/* Datasheet: POR releases ~500us after supplies are stable */
> +	fsleep(500);
> +
> +	reset = devm_reset_control_get_optional_exclusive(dev, NULL);
> +	if (IS_ERR(reset))
> +		return dev_err_probe(dev, PTR_ERR(reset), "failed to get reset\n");
> +
> +	if (reset) {
> +		/* Datasheet: tw(RSL), the RESET low pulse, is 250ns minimum */
> +		fsleep(1);
> +
> +		ret = reset_control_deassert(reset);
> +		if (ret)
> +			return dev_err_probe(dev, ret, "failed to deassert reset\n");
> +	} else {
> +		ret = ads112c04_write_cmd(client, ADS112C04_CMD_RESET);
> +		if (ret < 0)
> +			return ret;
> +	}
> +
> +	/* Datasheet: td(RSSTA) is 100ns minimum after the RESET rising edge */
> +	fsleep(1);

Perhaps simply ndelay(100) ?

> +	/*
> +	 * Initialize CONFIG0 with all fields explicit: gain of 1 with the PGA
> +	 * bypassed, which allows full-scale single-ended measurements. The MUX
> +	 * field is updated per channel before each conversion.
> +	 */
> +	st->config0 = FIELD_PREP(ADS112C04_CONF0_MUX,
> +				 ADS112C04_CONF0_MUX_AIN0_AIN1) |
> +		      FIELD_PREP(ADS112C04_CONF0_GAIN,
> +				 ADS112C04_CONF0_GAIN_X1) |
> +		      ADS112C04_CONF0_PGA_BYPASS;
> +
> +	ret = ads112c04_write_reg(client, ADS112C04_REG_CONFIG0, st->config0);
> +	if (ret)
> +		return ret;
> +
> +	st->config1 = FIELD_PREP(ADS112C04_CONF1_DR,
> +				 ADS112C04_CONF1_DR_20SPS) |
> +		      FIELD_PREP(ADS112C04_CONF1_MODE,
> +				 ADS112C04_CONF1_MODE_NORMAL) |
> +		      FIELD_PREP(ADS112C04_CONF1_CM,
> +				 ADS112C04_CONF1_CM_SINGLE_SHOT) |
> +		      FIELD_PREP(ADS112C04_CONF1_VREF,
> +				 ADS112C04_CONF1_VREF_INTERNAL) |
> +		      FIELD_PREP(ADS112C04_CONF1_TS,
> +				 ADS112C04_CONF1_TS_DISABLED);
> +
> +	ret = ads112c04_write_reg(client, ADS112C04_REG_CONFIG1, st->config1);
> +	if (ret)
> +		return ret;
> +
> +	if (client->irq > 0) {
> +		ret = devm_request_irq(dev, client->irq, ads112c04_irq_handler, 0,
> +				       indio_dev->name, indio_dev);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	return devm_iio_device_register(dev, indio_dev);
> +}

-- 
With Best Regards,
Andy Shevchenko
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.