158 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Driver for Linear Technology LTC2471 and LTC2473 voltage monitors4 * The LTC2473 is identical to the 2471, but reports a differential signal.5 *6 * Copyright (C) 2017 Topic Embedded Products7 * Author: Mike Looijmans <mike.looijmans@topic.nl>8 */9 10#include <linux/err.h>11#include <linux/i2c.h>12#include <linux/kernel.h>13#include <linux/module.h>14#include <linux/iio/iio.h>15#include <linux/iio/sysfs.h>16 17enum ltc2471_chips {18 ltc2471,19 ltc2473,20};21 22struct ltc2471_data {23 struct i2c_client *client;24};25 26/* Reference voltage is 1.25V */27#define LTC2471_VREF 125028 29/* Read two bytes from the I2C bus to obtain the ADC result */30static int ltc2471_get_value(struct i2c_client *client)31{32 int ret;33 __be16 buf;34 35 ret = i2c_master_recv(client, (char *)&buf, sizeof(buf));36 if (ret < 0)37 return ret;38 if (ret != sizeof(buf))39 return -EIO;40 41 /* MSB first */42 return be16_to_cpu(buf);43}44 45static int ltc2471_read_raw(struct iio_dev *indio_dev,46 struct iio_chan_spec const *chan,47 int *val, int *val2, long info)48{49 struct ltc2471_data *data = iio_priv(indio_dev);50 int ret;51 52 switch (info) {53 case IIO_CHAN_INFO_RAW:54 ret = ltc2471_get_value(data->client);55 if (ret < 0)56 return ret;57 *val = ret;58 return IIO_VAL_INT;59 60 case IIO_CHAN_INFO_SCALE:61 if (chan->differential)62 /* Output ranges from -VREF to +VREF */63 *val = 2 * LTC2471_VREF;64 else65 /* Output ranges from 0 to VREF */66 *val = LTC2471_VREF;67 *val2 = 16; /* 16 data bits */68 return IIO_VAL_FRACTIONAL_LOG2;69 70 case IIO_CHAN_INFO_OFFSET:71 /* Only differential chip has this property */72 *val = -LTC2471_VREF;73 return IIO_VAL_INT;74 75 default:76 return -EINVAL;77 }78}79 80static const struct iio_chan_spec ltc2471_channel[] = {81 {82 .type = IIO_VOLTAGE,83 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),84 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),85 },86};87 88static const struct iio_chan_spec ltc2473_channel[] = {89 {90 .type = IIO_VOLTAGE,91 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),92 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |93 BIT(IIO_CHAN_INFO_OFFSET),94 .differential = 1,95 },96};97 98static const struct iio_info ltc2471_info = {99 .read_raw = ltc2471_read_raw,100};101 102static int ltc2471_i2c_probe(struct i2c_client *client)103{104 const struct i2c_device_id *id = i2c_client_get_device_id(client);105 struct iio_dev *indio_dev;106 struct ltc2471_data *data;107 int ret;108 109 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))110 return -EOPNOTSUPP;111 112 indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));113 if (!indio_dev)114 return -ENOMEM;115 116 data = iio_priv(indio_dev);117 data->client = client;118 119 indio_dev->name = id->name;120 indio_dev->info = <c2471_info;121 indio_dev->modes = INDIO_DIRECT_MODE;122 if (id->driver_data == ltc2473)123 indio_dev->channels = ltc2473_channel;124 else125 indio_dev->channels = ltc2471_channel;126 indio_dev->num_channels = 1;127 128 /* Trigger once to start conversion and check if chip is there */129 ret = ltc2471_get_value(client);130 if (ret < 0) {131 dev_err(&client->dev, "Cannot read from device.\n");132 return ret;133 }134 135 return devm_iio_device_register(&client->dev, indio_dev);136}137 138static const struct i2c_device_id ltc2471_i2c_id[] = {139 { "ltc2471", ltc2471 },140 { "ltc2473", ltc2473 },141 {}142};143MODULE_DEVICE_TABLE(i2c, ltc2471_i2c_id);144 145static struct i2c_driver ltc2471_i2c_driver = {146 .driver = {147 .name = "ltc2471",148 },149 .probe = ltc2471_i2c_probe,150 .id_table = ltc2471_i2c_id,151};152 153module_i2c_driver(ltc2471_i2c_driver);154 155MODULE_DESCRIPTION("LTC2471/LTC2473 ADC driver");156MODULE_AUTHOR("Topic Embedded Products");157MODULE_LICENSE("GPL v2");158