xref: /openbmc/linux/drivers/iio/adc/ltc2497-core.c (revision da8091f8)
169548b7cSUwe Kleine-König // SPDX-License-Identifier: GPL-2.0-only
269548b7cSUwe Kleine-König /*
369548b7cSUwe Kleine-König  * ltc2497-core.c - Common code for Analog Devices/Linear Technology
469548b7cSUwe Kleine-König  * LTC2496 and LTC2497 ADCs
569548b7cSUwe Kleine-König  *
669548b7cSUwe Kleine-König  * Copyright (C) 2017 Analog Devices Inc.
769548b7cSUwe Kleine-König  */
869548b7cSUwe Kleine-König 
969548b7cSUwe Kleine-König #include <linux/delay.h>
1069548b7cSUwe Kleine-König #include <linux/iio/iio.h>
1169548b7cSUwe Kleine-König #include <linux/iio/driver.h>
1269548b7cSUwe Kleine-König #include <linux/module.h>
13*da8091f8SNuno Sá #include <linux/mutex.h>
1469548b7cSUwe Kleine-König #include <linux/regulator/consumer.h>
1569548b7cSUwe Kleine-König 
1669548b7cSUwe Kleine-König #include "ltc2497.h"
1769548b7cSUwe Kleine-König 
1869548b7cSUwe Kleine-König #define LTC2497_SGL			BIT(4)
1969548b7cSUwe Kleine-König #define LTC2497_DIFF			0
2069548b7cSUwe Kleine-König #define LTC2497_SIGN			BIT(3)
2169548b7cSUwe Kleine-König 
ltc2497core_wait_conv(struct ltc2497core_driverdata * ddata)2269548b7cSUwe Kleine-König static int ltc2497core_wait_conv(struct ltc2497core_driverdata *ddata)
2369548b7cSUwe Kleine-König {
2469548b7cSUwe Kleine-König 	s64 time_elapsed;
2569548b7cSUwe Kleine-König 
2669548b7cSUwe Kleine-König 	time_elapsed = ktime_ms_delta(ktime_get(), ddata->time_prev);
2769548b7cSUwe Kleine-König 
2869548b7cSUwe Kleine-König 	if (time_elapsed < LTC2497_CONVERSION_TIME_MS) {
2969548b7cSUwe Kleine-König 		/* delay if conversion time not passed
3069548b7cSUwe Kleine-König 		 * since last read or write
3169548b7cSUwe Kleine-König 		 */
3269548b7cSUwe Kleine-König 		if (msleep_interruptible(
3369548b7cSUwe Kleine-König 		    LTC2497_CONVERSION_TIME_MS - time_elapsed))
3469548b7cSUwe Kleine-König 			return -ERESTARTSYS;
3569548b7cSUwe Kleine-König 
3669548b7cSUwe Kleine-König 		return 0;
3769548b7cSUwe Kleine-König 	}
3869548b7cSUwe Kleine-König 
3969548b7cSUwe Kleine-König 	if (time_elapsed - LTC2497_CONVERSION_TIME_MS <= 0) {
4069548b7cSUwe Kleine-König 		/* We're in automatic mode -
4169548b7cSUwe Kleine-König 		 * so the last reading is still not outdated
4269548b7cSUwe Kleine-König 		 */
4369548b7cSUwe Kleine-König 		return 0;
4469548b7cSUwe Kleine-König 	}
4569548b7cSUwe Kleine-König 
4669548b7cSUwe Kleine-König 	return 1;
4769548b7cSUwe Kleine-König }
4869548b7cSUwe Kleine-König 
ltc2497core_read(struct ltc2497core_driverdata * ddata,u8 address,int * val)4969548b7cSUwe Kleine-König static int ltc2497core_read(struct ltc2497core_driverdata *ddata, u8 address, int *val)
5069548b7cSUwe Kleine-König {
5169548b7cSUwe Kleine-König 	int ret;
5269548b7cSUwe Kleine-König 
5369548b7cSUwe Kleine-König 	ret = ltc2497core_wait_conv(ddata);
5469548b7cSUwe Kleine-König 	if (ret < 0)
5569548b7cSUwe Kleine-König 		return ret;
5669548b7cSUwe Kleine-König 
5769548b7cSUwe Kleine-König 	if (ret || ddata->addr_prev != address) {
5869548b7cSUwe Kleine-König 		ret = ddata->result_and_measure(ddata, address, NULL);
5969548b7cSUwe Kleine-König 		if (ret < 0)
6069548b7cSUwe Kleine-König 			return ret;
6169548b7cSUwe Kleine-König 		ddata->addr_prev = address;
6269548b7cSUwe Kleine-König 
6369548b7cSUwe Kleine-König 		if (msleep_interruptible(LTC2497_CONVERSION_TIME_MS))
6469548b7cSUwe Kleine-König 			return -ERESTARTSYS;
6569548b7cSUwe Kleine-König 	}
6669548b7cSUwe Kleine-König 
6769548b7cSUwe Kleine-König 	ret = ddata->result_and_measure(ddata, address, val);
6869548b7cSUwe Kleine-König 	if (ret < 0)
6969548b7cSUwe Kleine-König 		return ret;
7069548b7cSUwe Kleine-König 
7169548b7cSUwe Kleine-König 	ddata->time_prev = ktime_get();
7269548b7cSUwe Kleine-König 
7369548b7cSUwe Kleine-König 	return ret;
7469548b7cSUwe Kleine-König }
7569548b7cSUwe Kleine-König 
ltc2497core_read_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int * val,int * val2,long mask)7669548b7cSUwe Kleine-König static int ltc2497core_read_raw(struct iio_dev *indio_dev,
7769548b7cSUwe Kleine-König 			    struct iio_chan_spec const *chan,
7869548b7cSUwe Kleine-König 			    int *val, int *val2, long mask)
7969548b7cSUwe Kleine-König {
8069548b7cSUwe Kleine-König 	struct ltc2497core_driverdata *ddata = iio_priv(indio_dev);
8169548b7cSUwe Kleine-König 	int ret;
8269548b7cSUwe Kleine-König 
8369548b7cSUwe Kleine-König 	switch (mask) {
8469548b7cSUwe Kleine-König 	case IIO_CHAN_INFO_RAW:
85*da8091f8SNuno Sá 		mutex_lock(&ddata->lock);
8669548b7cSUwe Kleine-König 		ret = ltc2497core_read(ddata, chan->address, val);
87*da8091f8SNuno Sá 		mutex_unlock(&ddata->lock);
8869548b7cSUwe Kleine-König 		if (ret < 0)
8969548b7cSUwe Kleine-König 			return ret;
9069548b7cSUwe Kleine-König 
9169548b7cSUwe Kleine-König 		return IIO_VAL_INT;
9269548b7cSUwe Kleine-König 
9369548b7cSUwe Kleine-König 	case IIO_CHAN_INFO_SCALE:
9469548b7cSUwe Kleine-König 		ret = regulator_get_voltage(ddata->ref);
9569548b7cSUwe Kleine-König 		if (ret < 0)
9669548b7cSUwe Kleine-König 			return ret;
9769548b7cSUwe Kleine-König 
9869548b7cSUwe Kleine-König 		*val = ret / 1000;
992187cfebSCiprian Regus 		*val2 = ddata->chip_info->resolution + 1;
10069548b7cSUwe Kleine-König 
10169548b7cSUwe Kleine-König 		return IIO_VAL_FRACTIONAL_LOG2;
10269548b7cSUwe Kleine-König 
10369548b7cSUwe Kleine-König 	default:
10469548b7cSUwe Kleine-König 		return -EINVAL;
10569548b7cSUwe Kleine-König 	}
10669548b7cSUwe Kleine-König }
10769548b7cSUwe Kleine-König 
10869548b7cSUwe Kleine-König #define LTC2497_CHAN(_chan, _addr, _ds_name) { \
10969548b7cSUwe Kleine-König 	.type = IIO_VOLTAGE, \
11069548b7cSUwe Kleine-König 	.indexed = 1, \
11169548b7cSUwe Kleine-König 	.channel = (_chan), \
11269548b7cSUwe Kleine-König 	.address = (_addr | (_chan / 2) | ((_chan & 1) ? LTC2497_SIGN : 0)), \
11369548b7cSUwe Kleine-König 	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
11469548b7cSUwe Kleine-König 	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
11569548b7cSUwe Kleine-König 	.datasheet_name = (_ds_name), \
11669548b7cSUwe Kleine-König }
11769548b7cSUwe Kleine-König 
11869548b7cSUwe Kleine-König #define LTC2497_CHAN_DIFF(_chan, _addr) { \
11969548b7cSUwe Kleine-König 	.type = IIO_VOLTAGE, \
12069548b7cSUwe Kleine-König 	.indexed = 1, \
12169548b7cSUwe Kleine-König 	.channel = (_chan) * 2 + ((_addr) & LTC2497_SIGN ? 1 : 0), \
12269548b7cSUwe Kleine-König 	.channel2 = (_chan) * 2 + ((_addr) & LTC2497_SIGN ? 0 : 1),\
12369548b7cSUwe Kleine-König 	.address = (_addr | _chan), \
12469548b7cSUwe Kleine-König 	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
12569548b7cSUwe Kleine-König 	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
12669548b7cSUwe Kleine-König 	.differential = 1, \
12769548b7cSUwe Kleine-König }
12869548b7cSUwe Kleine-König 
12969548b7cSUwe Kleine-König static const struct iio_chan_spec ltc2497core_channel[] = {
13069548b7cSUwe Kleine-König 	LTC2497_CHAN(0, LTC2497_SGL, "CH0"),
13169548b7cSUwe Kleine-König 	LTC2497_CHAN(1, LTC2497_SGL, "CH1"),
13269548b7cSUwe Kleine-König 	LTC2497_CHAN(2, LTC2497_SGL, "CH2"),
13369548b7cSUwe Kleine-König 	LTC2497_CHAN(3, LTC2497_SGL, "CH3"),
13469548b7cSUwe Kleine-König 	LTC2497_CHAN(4, LTC2497_SGL, "CH4"),
13569548b7cSUwe Kleine-König 	LTC2497_CHAN(5, LTC2497_SGL, "CH5"),
13669548b7cSUwe Kleine-König 	LTC2497_CHAN(6, LTC2497_SGL, "CH6"),
13769548b7cSUwe Kleine-König 	LTC2497_CHAN(7, LTC2497_SGL, "CH7"),
13869548b7cSUwe Kleine-König 	LTC2497_CHAN(8, LTC2497_SGL, "CH8"),
13969548b7cSUwe Kleine-König 	LTC2497_CHAN(9, LTC2497_SGL, "CH9"),
14069548b7cSUwe Kleine-König 	LTC2497_CHAN(10, LTC2497_SGL, "CH10"),
14169548b7cSUwe Kleine-König 	LTC2497_CHAN(11, LTC2497_SGL, "CH11"),
14269548b7cSUwe Kleine-König 	LTC2497_CHAN(12, LTC2497_SGL, "CH12"),
14369548b7cSUwe Kleine-König 	LTC2497_CHAN(13, LTC2497_SGL, "CH13"),
14469548b7cSUwe Kleine-König 	LTC2497_CHAN(14, LTC2497_SGL, "CH14"),
14569548b7cSUwe Kleine-König 	LTC2497_CHAN(15, LTC2497_SGL, "CH15"),
14669548b7cSUwe Kleine-König 	LTC2497_CHAN_DIFF(0, LTC2497_DIFF),
14769548b7cSUwe Kleine-König 	LTC2497_CHAN_DIFF(1, LTC2497_DIFF),
14869548b7cSUwe Kleine-König 	LTC2497_CHAN_DIFF(2, LTC2497_DIFF),
14969548b7cSUwe Kleine-König 	LTC2497_CHAN_DIFF(3, LTC2497_DIFF),
15069548b7cSUwe Kleine-König 	LTC2497_CHAN_DIFF(4, LTC2497_DIFF),
15169548b7cSUwe Kleine-König 	LTC2497_CHAN_DIFF(5, LTC2497_DIFF),
15269548b7cSUwe Kleine-König 	LTC2497_CHAN_DIFF(6, LTC2497_DIFF),
15369548b7cSUwe Kleine-König 	LTC2497_CHAN_DIFF(7, LTC2497_DIFF),
15469548b7cSUwe Kleine-König 	LTC2497_CHAN_DIFF(0, LTC2497_DIFF | LTC2497_SIGN),
15569548b7cSUwe Kleine-König 	LTC2497_CHAN_DIFF(1, LTC2497_DIFF | LTC2497_SIGN),
15669548b7cSUwe Kleine-König 	LTC2497_CHAN_DIFF(2, LTC2497_DIFF | LTC2497_SIGN),
15769548b7cSUwe Kleine-König 	LTC2497_CHAN_DIFF(3, LTC2497_DIFF | LTC2497_SIGN),
15869548b7cSUwe Kleine-König 	LTC2497_CHAN_DIFF(4, LTC2497_DIFF | LTC2497_SIGN),
15969548b7cSUwe Kleine-König 	LTC2497_CHAN_DIFF(5, LTC2497_DIFF | LTC2497_SIGN),
16069548b7cSUwe Kleine-König 	LTC2497_CHAN_DIFF(6, LTC2497_DIFF | LTC2497_SIGN),
16169548b7cSUwe Kleine-König 	LTC2497_CHAN_DIFF(7, LTC2497_DIFF | LTC2497_SIGN),
16269548b7cSUwe Kleine-König };
16369548b7cSUwe Kleine-König 
16469548b7cSUwe Kleine-König static const struct iio_info ltc2497core_info = {
16569548b7cSUwe Kleine-König 	.read_raw = ltc2497core_read_raw,
16669548b7cSUwe Kleine-König };
16769548b7cSUwe Kleine-König 
ltc2497core_probe(struct device * dev,struct iio_dev * indio_dev)16869548b7cSUwe Kleine-König int ltc2497core_probe(struct device *dev, struct iio_dev *indio_dev)
16969548b7cSUwe Kleine-König {
17069548b7cSUwe Kleine-König 	struct ltc2497core_driverdata *ddata = iio_priv(indio_dev);
17169548b7cSUwe Kleine-König 	int ret;
17269548b7cSUwe Kleine-König 
1731695c52aSCiprian Regus 	/*
1741695c52aSCiprian Regus 	 * Keep using dev_name() for the iio_dev's name on some of the parts,
1751695c52aSCiprian Regus 	 * since updating it would result in a ABI breakage.
1761695c52aSCiprian Regus 	 */
1771695c52aSCiprian Regus 	if (ddata->chip_info->name)
1781695c52aSCiprian Regus 		indio_dev->name = ddata->chip_info->name;
1791695c52aSCiprian Regus 	else
18069548b7cSUwe Kleine-König 		indio_dev->name = dev_name(dev);
1811695c52aSCiprian Regus 
18269548b7cSUwe Kleine-König 	indio_dev->info = &ltc2497core_info;
18369548b7cSUwe Kleine-König 	indio_dev->modes = INDIO_DIRECT_MODE;
18469548b7cSUwe Kleine-König 	indio_dev->channels = ltc2497core_channel;
18569548b7cSUwe Kleine-König 	indio_dev->num_channels = ARRAY_SIZE(ltc2497core_channel);
18669548b7cSUwe Kleine-König 
18769548b7cSUwe Kleine-König 	ret = ddata->result_and_measure(ddata, LTC2497_CONFIG_DEFAULT, NULL);
18869548b7cSUwe Kleine-König 	if (ret < 0)
18969548b7cSUwe Kleine-König 		return ret;
19069548b7cSUwe Kleine-König 
19169548b7cSUwe Kleine-König 	ddata->ref = devm_regulator_get(dev, "vref");
192291cb0b3SKrzysztof Kozlowski 	if (IS_ERR(ddata->ref))
193291cb0b3SKrzysztof Kozlowski 		return dev_err_probe(dev, PTR_ERR(ddata->ref),
194291cb0b3SKrzysztof Kozlowski 				     "Failed to get vref regulator\n");
19569548b7cSUwe Kleine-König 
19669548b7cSUwe Kleine-König 	ret = regulator_enable(ddata->ref);
19769548b7cSUwe Kleine-König 	if (ret < 0) {
19869548b7cSUwe Kleine-König 		dev_err(dev, "Failed to enable vref regulator: %pe\n",
19969548b7cSUwe Kleine-König 			ERR_PTR(ret));
20069548b7cSUwe Kleine-König 		return ret;
20169548b7cSUwe Kleine-König 	}
20269548b7cSUwe Kleine-König 
20369548b7cSUwe Kleine-König 	if (dev->platform_data) {
20469548b7cSUwe Kleine-König 		struct iio_map *plat_data;
20569548b7cSUwe Kleine-König 
20669548b7cSUwe Kleine-König 		plat_data = (struct iio_map *)dev->platform_data;
20769548b7cSUwe Kleine-König 
20869548b7cSUwe Kleine-König 		ret = iio_map_array_register(indio_dev, plat_data);
20969548b7cSUwe Kleine-König 		if (ret) {
21069548b7cSUwe Kleine-König 			dev_err(&indio_dev->dev, "iio map err: %d\n", ret);
21169548b7cSUwe Kleine-König 			goto err_regulator_disable;
21269548b7cSUwe Kleine-König 		}
21369548b7cSUwe Kleine-König 	}
21469548b7cSUwe Kleine-König 
21569548b7cSUwe Kleine-König 	ddata->addr_prev = LTC2497_CONFIG_DEFAULT;
21669548b7cSUwe Kleine-König 	ddata->time_prev = ktime_get();
21769548b7cSUwe Kleine-König 
218*da8091f8SNuno Sá 	mutex_init(&ddata->lock);
219*da8091f8SNuno Sá 
22069548b7cSUwe Kleine-König 	ret = iio_device_register(indio_dev);
22169548b7cSUwe Kleine-König 	if (ret < 0)
22269548b7cSUwe Kleine-König 		goto err_array_unregister;
22369548b7cSUwe Kleine-König 
22469548b7cSUwe Kleine-König 	return 0;
22569548b7cSUwe Kleine-König 
22669548b7cSUwe Kleine-König err_array_unregister:
22769548b7cSUwe Kleine-König 	iio_map_array_unregister(indio_dev);
22869548b7cSUwe Kleine-König 
22969548b7cSUwe Kleine-König err_regulator_disable:
23069548b7cSUwe Kleine-König 	regulator_disable(ddata->ref);
23169548b7cSUwe Kleine-König 
23269548b7cSUwe Kleine-König 	return ret;
23369548b7cSUwe Kleine-König }
23469548b7cSUwe Kleine-König EXPORT_SYMBOL_NS(ltc2497core_probe, LTC2497);
23569548b7cSUwe Kleine-König 
ltc2497core_remove(struct iio_dev * indio_dev)23669548b7cSUwe Kleine-König void ltc2497core_remove(struct iio_dev *indio_dev)
23769548b7cSUwe Kleine-König {
23869548b7cSUwe Kleine-König 	struct ltc2497core_driverdata *ddata = iio_priv(indio_dev);
23969548b7cSUwe Kleine-König 
24069548b7cSUwe Kleine-König 	iio_device_unregister(indio_dev);
24169548b7cSUwe Kleine-König 
24269548b7cSUwe Kleine-König 	iio_map_array_unregister(indio_dev);
24369548b7cSUwe Kleine-König 
24469548b7cSUwe Kleine-König 	regulator_disable(ddata->ref);
24569548b7cSUwe Kleine-König }
24669548b7cSUwe Kleine-König EXPORT_SYMBOL_NS(ltc2497core_remove, LTC2497);
24769548b7cSUwe Kleine-König 
24869548b7cSUwe Kleine-König MODULE_DESCRIPTION("common code for LTC2496/LTC2497 drivers");
24969548b7cSUwe Kleine-König MODULE_LICENSE("GPL v2");
250