xref: /openbmc/linux/drivers/iio/adc/ltc2485.c (revision 2612e3bbc0386368a850140a6c9b990cd496a5ec)
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 = &ltc2485_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