brintos

brintos / linux-shallow public Read only

0
0
Text · 7.3 KiB · 31564af Raw
351 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * AD8366 and similar Gain Amplifiers4 * This driver supports the following gain amplifiers:5 *   AD8366 Dual-Digital Variable Gain Amplifier (VGA)6 *   ADA4961 BiCMOS RF Digital Gain Amplifier (DGA)7 *   ADL5240 Digitally controlled variable gain amplifier (VGA)8 *   HMC792A 0.25 dB LSB GaAs MMIC 6-Bit Digital Attenuator9 *   HMC1119 0.25 dB LSB, 7-Bit, Silicon Digital Attenuator10 *11 * Copyright 2012-2019 Analog Devices Inc.12 */13 14#include <linux/device.h>15#include <linux/kernel.h>16#include <linux/slab.h>17#include <linux/sysfs.h>18#include <linux/spi/spi.h>19#include <linux/regulator/consumer.h>20#include <linux/gpio/consumer.h>21#include <linux/err.h>22#include <linux/module.h>23#include <linux/bitrev.h>24 25#include <linux/iio/iio.h>26#include <linux/iio/sysfs.h>27 28enum ad8366_type {29	ID_AD8366,30	ID_ADA4961,31	ID_ADL5240,32	ID_HMC792,33	ID_HMC1119,34};35 36struct ad8366_info {37	int gain_min;38	int gain_max;39};40 41struct ad8366_state {42	struct spi_device	*spi;43	struct regulator	*reg;44	struct mutex            lock; /* protect sensor state */45	struct gpio_desc	*reset_gpio;46	unsigned char		ch[2];47	enum ad8366_type	type;48	struct ad8366_info	*info;49	/*50	 * DMA (thus cache coherency maintenance) may require the51	 * transfer buffers to live in their own cache lines.52	 */53	unsigned char		data[2] __aligned(IIO_DMA_MINALIGN);54};55 56static struct ad8366_info ad8366_infos[] = {57	[ID_AD8366] = {58		.gain_min = 4500,59		.gain_max = 20500,60	},61	[ID_ADA4961] = {62		.gain_min = -6000,63		.gain_max = 15000,64	},65	[ID_ADL5240] = {66		.gain_min = -11500,67		.gain_max = 20000,68	},69	[ID_HMC792] = {70		.gain_min = -15750,71		.gain_max = 0,72	},73	[ID_HMC1119] = {74		.gain_min = -31750,75		.gain_max = 0,76	},77};78 79static int ad8366_write(struct iio_dev *indio_dev,80			unsigned char ch_a, unsigned char ch_b)81{82	struct ad8366_state *st = iio_priv(indio_dev);83	int ret;84 85	switch (st->type) {86	case ID_AD8366:87		ch_a = bitrev8(ch_a & 0x3F);88		ch_b = bitrev8(ch_b & 0x3F);89 90		st->data[0] = ch_b >> 4;91		st->data[1] = (ch_b << 4) | (ch_a >> 2);92		break;93	case ID_ADA4961:94		st->data[0] = ch_a & 0x1F;95		break;96	case ID_ADL5240:97		st->data[0] = (ch_a & 0x3F);98		break;99	case ID_HMC792:100	case ID_HMC1119:101		st->data[0] = ch_a;102		break;103	}104 105	ret = spi_write(st->spi, st->data, indio_dev->num_channels);106	if (ret < 0)107		dev_err(&indio_dev->dev, "write failed (%d)", ret);108 109	return ret;110}111 112static int ad8366_read_raw(struct iio_dev *indio_dev,113			   struct iio_chan_spec const *chan,114			   int *val,115			   int *val2,116			   long m)117{118	struct ad8366_state *st = iio_priv(indio_dev);119	int ret;120	int code, gain = 0;121 122	mutex_lock(&st->lock);123	switch (m) {124	case IIO_CHAN_INFO_HARDWAREGAIN:125		code = st->ch[chan->channel];126 127		switch (st->type) {128		case ID_AD8366:129			gain = code * 253 + 4500;130			break;131		case ID_ADA4961:132			gain = 15000 - code * 1000;133			break;134		case ID_ADL5240:135			gain = 20000 - 31500 + code * 500;136			break;137		case ID_HMC792:138			gain = -1 * code * 500;139			break;140		case ID_HMC1119:141			gain = -1 * code * 250;142			break;143		}144 145		/* Values in dB */146		*val = gain / 1000;147		*val2 = (gain % 1000) * 1000;148 149		ret = IIO_VAL_INT_PLUS_MICRO_DB;150		break;151	default:152		ret = -EINVAL;153	}154	mutex_unlock(&st->lock);155 156	return ret;157};158 159static int ad8366_write_raw(struct iio_dev *indio_dev,160			    struct iio_chan_spec const *chan,161			    int val,162			    int val2,163			    long mask)164{165	struct ad8366_state *st = iio_priv(indio_dev);166	struct ad8366_info *inf = st->info;167	int code = 0, gain;168	int ret;169 170	/* Values in dB */171	if (val < 0)172		gain = (val * 1000) - (val2 / 1000);173	else174		gain = (val * 1000) + (val2 / 1000);175 176	if (gain > inf->gain_max || gain < inf->gain_min)177		return -EINVAL;178 179	switch (st->type) {180	case ID_AD8366:181		code = (gain - 4500) / 253;182		break;183	case ID_ADA4961:184		code = (15000 - gain) / 1000;185		break;186	case ID_ADL5240:187		code = ((gain - 500 - 20000) / 500) & 0x3F;188		break;189	case ID_HMC792:190		code = (abs(gain) / 500) & 0x3F;191		break;192	case ID_HMC1119:193		code = (abs(gain) / 250) & 0x7F;194		break;195	}196 197	mutex_lock(&st->lock);198	switch (mask) {199	case IIO_CHAN_INFO_HARDWAREGAIN:200		st->ch[chan->channel] = code;201		ret = ad8366_write(indio_dev, st->ch[0], st->ch[1]);202		break;203	default:204		ret = -EINVAL;205	}206	mutex_unlock(&st->lock);207 208	return ret;209}210 211static int ad8366_write_raw_get_fmt(struct iio_dev *indio_dev,212				    struct iio_chan_spec const *chan,213				    long mask)214{215	switch (mask) {216	case IIO_CHAN_INFO_HARDWAREGAIN:217		return IIO_VAL_INT_PLUS_MICRO_DB;218	default:219		return -EINVAL;220	}221}222 223static const struct iio_info ad8366_info = {224	.read_raw = &ad8366_read_raw,225	.write_raw = &ad8366_write_raw,226	.write_raw_get_fmt = &ad8366_write_raw_get_fmt,227};228 229#define AD8366_CHAN(_channel) {				\230	.type = IIO_VOLTAGE,				\231	.output = 1,					\232	.indexed = 1,					\233	.channel = _channel,				\234	.info_mask_separate = BIT(IIO_CHAN_INFO_HARDWAREGAIN),\235}236 237static const struct iio_chan_spec ad8366_channels[] = {238	AD8366_CHAN(0),239	AD8366_CHAN(1),240};241 242static const struct iio_chan_spec ada4961_channels[] = {243	AD8366_CHAN(0),244};245 246static int ad8366_probe(struct spi_device *spi)247{248	struct iio_dev *indio_dev;249	struct ad8366_state *st;250	int ret;251 252	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));253	if (indio_dev == NULL)254		return -ENOMEM;255 256	st = iio_priv(indio_dev);257 258	st->reg = devm_regulator_get(&spi->dev, "vcc");259	if (!IS_ERR(st->reg)) {260		ret = regulator_enable(st->reg);261		if (ret)262			return ret;263	}264 265	spi_set_drvdata(spi, indio_dev);266	mutex_init(&st->lock);267	st->spi = spi;268	st->type = spi_get_device_id(spi)->driver_data;269 270	switch (st->type) {271	case ID_AD8366:272		indio_dev->channels = ad8366_channels;273		indio_dev->num_channels = ARRAY_SIZE(ad8366_channels);274		break;275	case ID_ADA4961:276	case ID_ADL5240:277	case ID_HMC792:278	case ID_HMC1119:279		st->reset_gpio = devm_gpiod_get_optional(&spi->dev, "reset", GPIOD_OUT_HIGH);280		if (IS_ERR(st->reset_gpio)) {281			ret = PTR_ERR(st->reset_gpio);282			goto error_disable_reg;283		}284		indio_dev->channels = ada4961_channels;285		indio_dev->num_channels = ARRAY_SIZE(ada4961_channels);286		break;287	default:288		dev_err(&spi->dev, "Invalid device ID\n");289		ret = -EINVAL;290		goto error_disable_reg;291	}292 293	st->info = &ad8366_infos[st->type];294	indio_dev->name = spi_get_device_id(spi)->name;295	indio_dev->info = &ad8366_info;296	indio_dev->modes = INDIO_DIRECT_MODE;297 298	ret = ad8366_write(indio_dev, 0, 0);299	if (ret < 0)300		goto error_disable_reg;301 302	ret = iio_device_register(indio_dev);303	if (ret)304		goto error_disable_reg;305 306	return 0;307 308error_disable_reg:309	if (!IS_ERR(st->reg))310		regulator_disable(st->reg);311 312	return ret;313}314 315static void ad8366_remove(struct spi_device *spi)316{317	struct iio_dev *indio_dev = spi_get_drvdata(spi);318	struct ad8366_state *st = iio_priv(indio_dev);319	struct regulator *reg = st->reg;320 321	iio_device_unregister(indio_dev);322 323	if (!IS_ERR(reg))324		regulator_disable(reg);325}326 327static const struct spi_device_id ad8366_id[] = {328	{"ad8366",  ID_AD8366},329	{"ada4961", ID_ADA4961},330	{"adl5240", ID_ADL5240},331	{"hmc792a", ID_HMC792},332	{"hmc1119", ID_HMC1119},333	{}334};335MODULE_DEVICE_TABLE(spi, ad8366_id);336 337static struct spi_driver ad8366_driver = {338	.driver = {339		.name	= KBUILD_MODNAME,340	},341	.probe		= ad8366_probe,342	.remove		= ad8366_remove,343	.id_table	= ad8366_id,344};345 346module_spi_driver(ad8366_driver);347 348MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>");349MODULE_DESCRIPTION("Analog Devices AD8366 and similar Gain Amplifiers");350MODULE_LICENSE("GPL v2");351