Re: [PATCH 1/3] iio: adc: add ltc2309 support
From: Krzysztof Kozlowski
Date: Thu Aug 24 2023 - 14:01:03 EST
On 24/08/2023 18:55, Liam Beguin wrote:
> The LTC2309 is an 8-Channel, 12-Bit SAR ADC with an I2C Interface.
>
> This implements support for all single-ended and differential channels,
> in unipolar mode only.
>
> Signed-off-by: Liam Beguin <liambeguin@xxxxxxxxx>
> ---
> drivers/iio/adc/Kconfig | 10 ++
> drivers/iio/adc/Makefile | 1 +
> drivers/iio/adc/ltc2309.c | 232 ++++++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 243 insertions(+)
>
> +static int ltc2309_read_raw(struct iio_dev *indio_dev,
> + struct iio_chan_spec const *chan, int *val,
> + int *val2, long mask)
> +{
> + struct ltc2309 *ltc2309 = iio_priv(indio_dev);
> + u16 buf;
> + int ret;
> + u8 din;
> +
> + mutex_lock(<c2309->lock);
> +
> + switch (mask) {
> + case IIO_CHAN_INFO_RAW:
> + din = FIELD_PREP(LTC2309_DIN_CH_MASK, chan->address & 0x0f) |
> + FIELD_PREP(LTC2309_DIN_UNI, 1) |
> + FIELD_PREP(LTC2309_DIN_SLEEP, 0);
> +
> + ret = i2c_smbus_write_byte(ltc2309->client, din);
> + if (ret < 0) {
> + dev_err(ltc2309->dev, "i2c command failed: %pe\n",
> + ERR_PTR(ret));
> + goto out;
> + }
> +
> + ret = i2c_master_recv(ltc2309->client, (char *)&buf, 2);
> + if (ret < 0) {
> + dev_err(ltc2309->dev, "i2c read failed: %pe\n",
> + ERR_PTR(ret));
> + goto out;
> + }
> +
> + *val = be16_to_cpu(buf) >> 4;
> +
> + ret = IIO_VAL_INT;
> + break;
> + case IIO_CHAN_INFO_SCALE:
> + *val = ltc2309->vref_mv;
> + *val2 = LTC2309_ADC_RESOLUTION;
> + ret = IIO_VAL_FRACTIONAL_LOG2;
Why this case is in critical section?
> + break;
> + default:
> + ret = -EINVAL;
> + break;
> + }
> +
> +out:
> + mutex_unlock(<c2309->lock);
> + return ret;
> +}
> +
> +static const struct iio_info ltc2309_info = {
> + .read_raw = ltc2309_read_raw,
> +};
> +
> +static int ltc2309_probe(struct i2c_client *client,
> + const struct i2c_device_id *id)
> +{
> + struct iio_dev *indio_dev;
> + struct ltc2309 *ltc2309;
> + int ret = 0;
> +
> + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*ltc2309));
> + if (!indio_dev)
> + return -ENOMEM;
> +
> + i2c_set_clientdata(client, indio_dev);
> +
> + ltc2309 = iio_priv(indio_dev);
> + ltc2309->dev = &indio_dev->dev;
> + ltc2309->client = client;
> + ltc2309->vref_mv = 4096; /* Default to the internal ref */
> +
> + indio_dev->name = DRIVER_NAME;
> + indio_dev->dev.parent = &client->dev;
> + indio_dev->modes = INDIO_DIRECT_MODE;
> + indio_dev->channels = ltc2309_channels;
> + indio_dev->num_channels = ARRAY_SIZE(ltc2309_channels);
> + indio_dev->info = <c2309_info;
> +
> + ltc2309->refcomp = devm_regulator_get_optional(&client->dev, "refcomp");
> + if (!IS_ERR_OR_NULL(ltc2309->refcomp)) {
> + ret = regulator_enable(ltc2309->refcomp);
> + if (ret) {
> + dev_err(ltc2309->dev, "failed to enable REFCOMP\n");
> + return ret;
> + }
> +
> + ret = regulator_get_voltage(ltc2309->refcomp);
> + if (ret < 0)
You have unbalanced regulator. Same in all further error paths.
> + return ret;
> +
> + ltc2309->vref_mv = ret / 1000;
> + if (ret)
> + return ret;
> + }
> +
> + mutex_init(<c2309->lock);
> +
> + return devm_iio_device_register(&client->dev, indio_dev);
> +}
> +
Best regards,
Krzysztof