1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
28c9e7b1bSAlison Schofield /*
38c9e7b1bSAlison Schofield * ltc2485.c - Driver for Linear Technology LTC2485 ADC
48c9e7b1bSAlison Schofield *
58c9e7b1bSAlison Schofield * Copyright (C) 2016 Alison Schofield <amsfield22@gmail.com>
68c9e7b1bSAlison Schofield *
78c9e7b1bSAlison Schofield * Datasheet: http://cds.linear.com/docs/en/datasheet/2485fd.pdf
88c9e7b1bSAlison Schofield */
98c9e7b1bSAlison Schofield
108c9e7b1bSAlison Schofield #include <linux/delay.h>
118c9e7b1bSAlison Schofield #include <linux/i2c.h>
128c9e7b1bSAlison Schofield #include <linux/module.h>
138c9e7b1bSAlison Schofield
148c9e7b1bSAlison Schofield #include <linux/iio/iio.h>
158c9e7b1bSAlison Schofield #include <linux/iio/sysfs.h>
168c9e7b1bSAlison Schofield
178c9e7b1bSAlison Schofield /* Power-on configuration: rejects both 50/60Hz, operates at 1x speed */
188c9e7b1bSAlison Schofield #define LTC2485_CONFIG_DEFAULT 0
198c9e7b1bSAlison Schofield
208c9e7b1bSAlison Schofield struct ltc2485_data {
218c9e7b1bSAlison Schofield struct i2c_client *client;
228c9e7b1bSAlison Schofield ktime_t time_prev; /* last conversion */
238c9e7b1bSAlison Schofield };
248c9e7b1bSAlison Schofield
ltc2485_wait_conv(struct ltc2485_data * data)258c9e7b1bSAlison Schofield static void ltc2485_wait_conv(struct ltc2485_data *data)
268c9e7b1bSAlison Schofield {
278c9e7b1bSAlison Schofield const unsigned int conv_time = 147; /* conversion time ms */
288c9e7b1bSAlison Schofield unsigned int time_elapsed;
298c9e7b1bSAlison Schofield
308c9e7b1bSAlison Schofield /* delay if conversion time not passed since last read or write */
318c9e7b1bSAlison Schofield time_elapsed = ktime_ms_delta(ktime_get(), data->time_prev);
328c9e7b1bSAlison Schofield
338c9e7b1bSAlison Schofield if (time_elapsed < conv_time)
348c9e7b1bSAlison Schofield msleep(conv_time - time_elapsed);
358c9e7b1bSAlison Schofield }
368c9e7b1bSAlison Schofield
ltc2485_read(struct ltc2485_data * data,int * val)378c9e7b1bSAlison Schofield static int ltc2485_read(struct ltc2485_data *data, int *val)
388c9e7b1bSAlison Schofield {
398c9e7b1bSAlison Schofield struct i2c_client *client = data->client;
408c9e7b1bSAlison Schofield __be32 buf = 0;
418c9e7b1bSAlison Schofield int ret;
428c9e7b1bSAlison Schofield
438c9e7b1bSAlison Schofield ltc2485_wait_conv(data);
448c9e7b1bSAlison Schofield
458c9e7b1bSAlison Schofield ret = i2c_master_recv(client, (char *)&buf, 4);
468c9e7b1bSAlison Schofield if (ret < 0) {
478c9e7b1bSAlison Schofield dev_err(&client->dev, "i2c_master_recv failed\n");
488c9e7b1bSAlison Schofield return ret;
498c9e7b1bSAlison Schofield }
508c9e7b1bSAlison Schofield data->time_prev = ktime_get();
518c9e7b1bSAlison Schofield *val = sign_extend32(be32_to_cpu(buf) >> 6, 24);
528c9e7b1bSAlison Schofield
538c9e7b1bSAlison Schofield return ret;
548c9e7b1bSAlison Schofield }
558c9e7b1bSAlison Schofield
ltc2485_read_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int * val,int * val2,long mask)568c9e7b1bSAlison Schofield static int ltc2485_read_raw(struct iio_dev *indio_dev,
578c9e7b1bSAlison Schofield struct iio_chan_spec const *chan,
588c9e7b1bSAlison Schofield int *val, int *val2, long mask)
598c9e7b1bSAlison Schofield {
608c9e7b1bSAlison Schofield struct ltc2485_data *data = iio_priv(indio_dev);
618c9e7b1bSAlison Schofield int ret;
628c9e7b1bSAlison Schofield
638c9e7b1bSAlison Schofield if (mask == IIO_CHAN_INFO_RAW) {
648c9e7b1bSAlison Schofield ret = ltc2485_read(data, val);
658c9e7b1bSAlison Schofield if (ret < 0)
668c9e7b1bSAlison Schofield return ret;
678c9e7b1bSAlison Schofield
688c9e7b1bSAlison Schofield return IIO_VAL_INT;
698c9e7b1bSAlison Schofield
708c9e7b1bSAlison Schofield } else if (mask == IIO_CHAN_INFO_SCALE) {
718c9e7b1bSAlison Schofield *val = 5000; /* on board vref millivolts */
728c9e7b1bSAlison Schofield *val2 = 25; /* 25 (24 + sign) data bits */
738c9e7b1bSAlison Schofield return IIO_VAL_FRACTIONAL_LOG2;
748c9e7b1bSAlison Schofield
758c9e7b1bSAlison Schofield } else {
768c9e7b1bSAlison Schofield return -EINVAL;
778c9e7b1bSAlison Schofield }
788c9e7b1bSAlison Schofield }
798c9e7b1bSAlison Schofield
808c9e7b1bSAlison Schofield static const struct iio_chan_spec ltc2485_channel[] = {
818c9e7b1bSAlison Schofield {
828c9e7b1bSAlison Schofield .type = IIO_VOLTAGE,
838c9e7b1bSAlison Schofield .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
848c9e7b1bSAlison Schofield .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE)
858c9e7b1bSAlison Schofield },
868c9e7b1bSAlison Schofield };
878c9e7b1bSAlison Schofield
888c9e7b1bSAlison Schofield static const struct iio_info ltc2485_info = {
898c9e7b1bSAlison Schofield .read_raw = ltc2485_read_raw,
908c9e7b1bSAlison Schofield };
918c9e7b1bSAlison Schofield
ltc2485_probe(struct i2c_client * client)9211e67cc9SUwe Kleine-König static int ltc2485_probe(struct i2c_client *client)
938c9e7b1bSAlison Schofield {
9411e67cc9SUwe Kleine-König const struct i2c_device_id *id = i2c_client_get_device_id(client);
958c9e7b1bSAlison Schofield struct iio_dev *indio_dev;
968c9e7b1bSAlison Schofield struct ltc2485_data *data;
978c9e7b1bSAlison Schofield int ret;
988c9e7b1bSAlison Schofield
998c9e7b1bSAlison Schofield if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C |
1008c9e7b1bSAlison Schofield I2C_FUNC_SMBUS_WRITE_BYTE))
1018c9e7b1bSAlison Schofield return -EOPNOTSUPP;
1028c9e7b1bSAlison Schofield
1038c9e7b1bSAlison Schofield indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
1048c9e7b1bSAlison Schofield if (!indio_dev)
1058c9e7b1bSAlison Schofield return -ENOMEM;
1068c9e7b1bSAlison Schofield
1078c9e7b1bSAlison Schofield data = iio_priv(indio_dev);
1088c9e7b1bSAlison Schofield i2c_set_clientdata(client, indio_dev);
1098c9e7b1bSAlison Schofield data->client = client;
1108c9e7b1bSAlison Schofield
1118c9e7b1bSAlison Schofield indio_dev->name = id->name;
1128c9e7b1bSAlison Schofield indio_dev->info = <c2485_info;
1138c9e7b1bSAlison Schofield indio_dev->modes = INDIO_DIRECT_MODE;
1148c9e7b1bSAlison Schofield indio_dev->channels = ltc2485_channel;
1158c9e7b1bSAlison Schofield indio_dev->num_channels = ARRAY_SIZE(ltc2485_channel);
1168c9e7b1bSAlison Schofield
1178c9e7b1bSAlison Schofield ret = i2c_smbus_write_byte(data->client, LTC2485_CONFIG_DEFAULT);
1188c9e7b1bSAlison Schofield if (ret < 0)
1198c9e7b1bSAlison Schofield return ret;
1208c9e7b1bSAlison Schofield
1218c9e7b1bSAlison Schofield data->time_prev = ktime_get();
1228c9e7b1bSAlison Schofield
1238c9e7b1bSAlison Schofield return devm_iio_device_register(&client->dev, indio_dev);
1248c9e7b1bSAlison Schofield }
1258c9e7b1bSAlison Schofield
1268c9e7b1bSAlison Schofield static const struct i2c_device_id ltc2485_id[] = {
1278c9e7b1bSAlison Schofield { "ltc2485", 0 },
1288c9e7b1bSAlison Schofield { }
1298c9e7b1bSAlison Schofield };
1308c9e7b1bSAlison Schofield MODULE_DEVICE_TABLE(i2c, ltc2485_id);
1318c9e7b1bSAlison Schofield
1328c9e7b1bSAlison Schofield static struct i2c_driver ltc2485_driver = {
1338c9e7b1bSAlison Schofield .driver = {
1348c9e7b1bSAlison Schofield .name = "ltc2485",
1358c9e7b1bSAlison Schofield },
136*7cf15f42SUwe Kleine-König .probe = ltc2485_probe,
1378c9e7b1bSAlison Schofield .id_table = ltc2485_id,
1388c9e7b1bSAlison Schofield };
1398c9e7b1bSAlison Schofield module_i2c_driver(ltc2485_driver);
1408c9e7b1bSAlison Schofield
1418c9e7b1bSAlison Schofield MODULE_AUTHOR("Alison Schofield <amsfield22@gmail.com>");
1428c9e7b1bSAlison Schofield MODULE_DESCRIPTION("Linear Technology LTC2485 ADC driver");
1438c9e7b1bSAlison Schofield MODULE_LICENSE("GPL v2");
144