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