brintos

brintos / linux-shallow public Read only

0
0
Text · 3.5 KiB · 97c417c Raw
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 = &ltc2471_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