brintos

brintos / linux-shallow public Read only

0
0
Text · 14.4 KiB · 2e3e33f Raw
649 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Analog devices AD5380, AD5381, AD5382, AD5383, AD5390, AD5391, AD53924 * multi-channel Digital to Analog Converters driver5 *6 * Copyright 2011 Analog Devices Inc.7 */8 9#include <linux/device.h>10#include <linux/err.h>11#include <linux/i2c.h>12#include <linux/kernel.h>13#include <linux/module.h>14#include <linux/spi/spi.h>15#include <linux/slab.h>16#include <linux/sysfs.h>17#include <linux/regmap.h>18#include <linux/regulator/consumer.h>19 20#include <linux/iio/iio.h>21#include <linux/iio/sysfs.h>22 23#define AD5380_REG_DATA(x)	(((x) << 2) | 3)24#define AD5380_REG_OFFSET(x)	(((x) << 2) | 2)25#define AD5380_REG_GAIN(x)	(((x) << 2) | 1)26#define AD5380_REG_SF_PWR_DOWN	(8 << 2)27#define AD5380_REG_SF_PWR_UP	(9 << 2)28#define AD5380_REG_SF_CTRL	(12 << 2)29 30#define AD5380_CTRL_PWR_DOWN_MODE_OFFSET	1331#define AD5380_CTRL_INT_VREF_2V5		BIT(12)32#define AD5380_CTRL_INT_VREF_EN			BIT(10)33 34/**35 * struct ad5380_chip_info - chip specific information36 * @channel_template:	channel specification template37 * @num_channels:	number of channels38 * @int_vref:		internal vref in uV39 */40struct ad5380_chip_info {41	struct iio_chan_spec	channel_template;42	unsigned int		num_channels;43	unsigned int		int_vref;44};45 46/**47 * struct ad5380_state - driver instance specific data48 * @regmap:		regmap instance used by the device49 * @chip_info:		chip model specific constants, available modes etc50 * @vref_reg:		vref supply regulator51 * @vref:		actual reference voltage used in uA52 * @pwr_down:		whether the chip is currently in power down mode53 * @lock:		lock to protect the data buffer during regmap ops54 */55struct ad5380_state {56	struct regmap			*regmap;57	const struct ad5380_chip_info	*chip_info;58	struct regulator		*vref_reg;59	int				vref;60	bool				pwr_down;61	struct mutex			lock;62};63 64enum ad5380_type {65	ID_AD5380_3,66	ID_AD5380_5,67	ID_AD5381_3,68	ID_AD5381_5,69	ID_AD5382_3,70	ID_AD5382_5,71	ID_AD5383_3,72	ID_AD5383_5,73	ID_AD5390_3,74	ID_AD5390_5,75	ID_AD5391_3,76	ID_AD5391_5,77	ID_AD5392_3,78	ID_AD5392_5,79};80 81static ssize_t ad5380_read_dac_powerdown(struct iio_dev *indio_dev,82	uintptr_t private, const struct iio_chan_spec *chan, char *buf)83{84	struct ad5380_state *st = iio_priv(indio_dev);85 86	return sysfs_emit(buf, "%d\n", st->pwr_down);87}88 89static ssize_t ad5380_write_dac_powerdown(struct iio_dev *indio_dev,90	 uintptr_t private, const struct iio_chan_spec *chan, const char *buf,91	 size_t len)92{93	struct ad5380_state *st = iio_priv(indio_dev);94	bool pwr_down;95	int ret;96 97	ret = kstrtobool(buf, &pwr_down);98	if (ret)99		return ret;100 101	mutex_lock(&st->lock);102 103	if (pwr_down)104		ret = regmap_write(st->regmap, AD5380_REG_SF_PWR_DOWN, 0);105	else106		ret = regmap_write(st->regmap, AD5380_REG_SF_PWR_UP, 0);107 108	st->pwr_down = pwr_down;109 110	mutex_unlock(&st->lock);111 112	return ret ? ret : len;113}114 115static const char * const ad5380_powerdown_modes[] = {116	"100kohm_to_gnd",117	"three_state",118};119 120static int ad5380_get_powerdown_mode(struct iio_dev *indio_dev,121	const struct iio_chan_spec *chan)122{123	struct ad5380_state *st = iio_priv(indio_dev);124	unsigned int mode;125	int ret;126 127	ret = regmap_read(st->regmap, AD5380_REG_SF_CTRL, &mode);128	if (ret)129		return ret;130 131	mode = (mode >> AD5380_CTRL_PWR_DOWN_MODE_OFFSET) & 1;132 133	return mode;134}135 136static int ad5380_set_powerdown_mode(struct iio_dev *indio_dev,137	const struct iio_chan_spec *chan, unsigned int mode)138{139	struct ad5380_state *st = iio_priv(indio_dev);140	int ret;141 142	ret = regmap_update_bits(st->regmap, AD5380_REG_SF_CTRL,143		1 << AD5380_CTRL_PWR_DOWN_MODE_OFFSET,144		mode << AD5380_CTRL_PWR_DOWN_MODE_OFFSET);145 146	return ret;147}148 149static const struct iio_enum ad5380_powerdown_mode_enum = {150	.items = ad5380_powerdown_modes,151	.num_items = ARRAY_SIZE(ad5380_powerdown_modes),152	.get = ad5380_get_powerdown_mode,153	.set = ad5380_set_powerdown_mode,154};155 156static unsigned int ad5380_info_to_reg(struct iio_chan_spec const *chan,157	long info)158{159	switch (info) {160	case IIO_CHAN_INFO_RAW:161		return AD5380_REG_DATA(chan->address);162	case IIO_CHAN_INFO_CALIBBIAS:163		return AD5380_REG_OFFSET(chan->address);164	case IIO_CHAN_INFO_CALIBSCALE:165		return AD5380_REG_GAIN(chan->address);166	default:167		break;168	}169 170	return 0;171}172 173static int ad5380_write_raw(struct iio_dev *indio_dev,174	struct iio_chan_spec const *chan, int val, int val2, long info)175{176	const unsigned int max_val = (1 << chan->scan_type.realbits);177	struct ad5380_state *st = iio_priv(indio_dev);178 179	switch (info) {180	case IIO_CHAN_INFO_RAW:181	case IIO_CHAN_INFO_CALIBSCALE:182		if (val >= max_val || val < 0)183			return -EINVAL;184 185		return regmap_write(st->regmap,186			ad5380_info_to_reg(chan, info),187			val << chan->scan_type.shift);188	case IIO_CHAN_INFO_CALIBBIAS:189		val += (1 << chan->scan_type.realbits) / 2;190		if (val >= max_val || val < 0)191			return -EINVAL;192 193		return regmap_write(st->regmap,194			AD5380_REG_OFFSET(chan->address),195			val << chan->scan_type.shift);196	default:197		break;198	}199	return -EINVAL;200}201 202static int ad5380_read_raw(struct iio_dev *indio_dev,203	struct iio_chan_spec const *chan, int *val, int *val2, long info)204{205	struct ad5380_state *st = iio_priv(indio_dev);206	int ret;207 208	switch (info) {209	case IIO_CHAN_INFO_RAW:210	case IIO_CHAN_INFO_CALIBSCALE:211		ret = regmap_read(st->regmap, ad5380_info_to_reg(chan, info),212					val);213		if (ret)214			return ret;215		*val >>= chan->scan_type.shift;216		return IIO_VAL_INT;217	case IIO_CHAN_INFO_CALIBBIAS:218		ret = regmap_read(st->regmap, AD5380_REG_OFFSET(chan->address),219					val);220		if (ret)221			return ret;222		*val >>= chan->scan_type.shift;223		*val -= (1 << chan->scan_type.realbits) / 2;224		return IIO_VAL_INT;225	case IIO_CHAN_INFO_SCALE:226		*val = 2 * st->vref;227		*val2 = chan->scan_type.realbits;228		return IIO_VAL_FRACTIONAL_LOG2;229	default:230		break;231	}232 233	return -EINVAL;234}235 236static const struct iio_info ad5380_info = {237	.read_raw = ad5380_read_raw,238	.write_raw = ad5380_write_raw,239};240 241static const struct iio_chan_spec_ext_info ad5380_ext_info[] = {242	{243		.name = "powerdown",244		.read = ad5380_read_dac_powerdown,245		.write = ad5380_write_dac_powerdown,246		.shared = IIO_SEPARATE,247	},248	IIO_ENUM("powerdown_mode", IIO_SHARED_BY_TYPE,249		 &ad5380_powerdown_mode_enum),250	IIO_ENUM_AVAILABLE("powerdown_mode", IIO_SHARED_BY_TYPE, &ad5380_powerdown_mode_enum),251	{ },252};253 254#define AD5380_CHANNEL(_bits) {					\255	.type = IIO_VOLTAGE,					\256	.indexed = 1,						\257	.output = 1,						\258	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |		\259		BIT(IIO_CHAN_INFO_CALIBSCALE) |			\260		BIT(IIO_CHAN_INFO_CALIBBIAS),			\261	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),	\262	.scan_type = {						\263		.sign = 'u',					\264		.realbits = (_bits),				\265		.storagebits =  16,				\266		.shift = 14 - (_bits),				\267	},							\268	.ext_info = ad5380_ext_info,				\269}270 271static const struct ad5380_chip_info ad5380_chip_info_tbl[] = {272	[ID_AD5380_3] = {273		.channel_template = AD5380_CHANNEL(14),274		.num_channels = 40,275		.int_vref = 1250,276	},277	[ID_AD5380_5] = {278		.channel_template = AD5380_CHANNEL(14),279		.num_channels = 40,280		.int_vref = 2500,281	},282	[ID_AD5381_3] = {283		.channel_template = AD5380_CHANNEL(12),284		.num_channels = 16,285		.int_vref = 1250,286	},287	[ID_AD5381_5] = {288		.channel_template = AD5380_CHANNEL(12),289		.num_channels = 16,290		.int_vref = 2500,291	},292	[ID_AD5382_3] = {293		.channel_template = AD5380_CHANNEL(14),294		.num_channels = 32,295		.int_vref = 1250,296	},297	[ID_AD5382_5] = {298		.channel_template = AD5380_CHANNEL(14),299		.num_channels = 32,300		.int_vref = 2500,301	},302	[ID_AD5383_3] = {303		.channel_template = AD5380_CHANNEL(12),304		.num_channels = 32,305		.int_vref = 1250,306	},307	[ID_AD5383_5] = {308		.channel_template = AD5380_CHANNEL(12),309		.num_channels = 32,310		.int_vref = 2500,311	},312	[ID_AD5390_3] = {313		.channel_template = AD5380_CHANNEL(14),314		.num_channels = 16,315		.int_vref = 1250,316	},317	[ID_AD5390_5] = {318		.channel_template = AD5380_CHANNEL(14),319		.num_channels = 16,320		.int_vref = 2500,321	},322	[ID_AD5391_3] = {323		.channel_template = AD5380_CHANNEL(12),324		.num_channels = 16,325		.int_vref = 1250,326	},327	[ID_AD5391_5] = {328		.channel_template = AD5380_CHANNEL(12),329		.num_channels = 16,330		.int_vref = 2500,331	},332	[ID_AD5392_3] = {333		.channel_template = AD5380_CHANNEL(14),334		.num_channels = 8,335		.int_vref = 1250,336	},337	[ID_AD5392_5] = {338		.channel_template = AD5380_CHANNEL(14),339		.num_channels = 8,340		.int_vref = 2500,341	},342};343 344static int ad5380_alloc_channels(struct iio_dev *indio_dev)345{346	struct ad5380_state *st = iio_priv(indio_dev);347	struct iio_chan_spec *channels;348	unsigned int i;349 350	channels = kcalloc(st->chip_info->num_channels,351			   sizeof(struct iio_chan_spec), GFP_KERNEL);352 353	if (!channels)354		return -ENOMEM;355 356	for (i = 0; i < st->chip_info->num_channels; ++i) {357		channels[i] = st->chip_info->channel_template;358		channels[i].channel = i;359		channels[i].address = i;360	}361 362	indio_dev->channels = channels;363 364	return 0;365}366 367static int ad5380_probe(struct device *dev, struct regmap *regmap,368			enum ad5380_type type, const char *name)369{370	struct iio_dev *indio_dev;371	struct ad5380_state *st;372	unsigned int ctrl = 0;373	int ret;374 375	indio_dev = devm_iio_device_alloc(dev, sizeof(*st));376	if (indio_dev == NULL) {377		dev_err(dev, "Failed to allocate iio device\n");378		return -ENOMEM;379	}380 381	st = iio_priv(indio_dev);382	dev_set_drvdata(dev, indio_dev);383 384	st->chip_info = &ad5380_chip_info_tbl[type];385	st->regmap = regmap;386 387	indio_dev->name = name;388	indio_dev->info = &ad5380_info;389	indio_dev->modes = INDIO_DIRECT_MODE;390	indio_dev->num_channels = st->chip_info->num_channels;391 392	mutex_init(&st->lock);393 394	ret = ad5380_alloc_channels(indio_dev);395	if (ret) {396		dev_err(dev, "Failed to allocate channel spec: %d\n", ret);397		return ret;398	}399 400	if (st->chip_info->int_vref == 2500)401		ctrl |= AD5380_CTRL_INT_VREF_2V5;402 403	st->vref_reg = devm_regulator_get(dev, "vref");404	if (!IS_ERR(st->vref_reg)) {405		ret = regulator_enable(st->vref_reg);406		if (ret) {407			dev_err(dev, "Failed to enable vref regulators: %d\n",408				ret);409			goto error_free_reg;410		}411 412		ret = regulator_get_voltage(st->vref_reg);413		if (ret < 0)414			goto error_disable_reg;415 416		st->vref = ret / 1000;417	} else {418		st->vref = st->chip_info->int_vref;419		ctrl |= AD5380_CTRL_INT_VREF_EN;420	}421 422	ret = regmap_write(st->regmap, AD5380_REG_SF_CTRL, ctrl);423	if (ret) {424		dev_err(dev, "Failed to write to device: %d\n", ret);425		goto error_disable_reg;426	}427 428	ret = iio_device_register(indio_dev);429	if (ret) {430		dev_err(dev, "Failed to register iio device: %d\n", ret);431		goto error_disable_reg;432	}433 434	return 0;435 436error_disable_reg:437	if (!IS_ERR(st->vref_reg))438		regulator_disable(st->vref_reg);439error_free_reg:440	kfree(indio_dev->channels);441 442	return ret;443}444 445static void ad5380_remove(struct device *dev)446{447	struct iio_dev *indio_dev = dev_get_drvdata(dev);448	struct ad5380_state *st = iio_priv(indio_dev);449 450	iio_device_unregister(indio_dev);451 452	kfree(indio_dev->channels);453 454	if (!IS_ERR(st->vref_reg))455		regulator_disable(st->vref_reg);456}457 458static bool ad5380_reg_false(struct device *dev, unsigned int reg)459{460	return false;461}462 463static const struct regmap_config ad5380_regmap_config = {464	.reg_bits = 10,465	.val_bits = 14,466 467	.max_register = AD5380_REG_DATA(40),468	.cache_type = REGCACHE_RBTREE,469 470	.volatile_reg = ad5380_reg_false,471	.readable_reg = ad5380_reg_false,472};473 474#if IS_ENABLED(CONFIG_SPI_MASTER)475 476static int ad5380_spi_probe(struct spi_device *spi)477{478	const struct spi_device_id *id = spi_get_device_id(spi);479	struct regmap *regmap;480 481	regmap = devm_regmap_init_spi(spi, &ad5380_regmap_config);482 483	if (IS_ERR(regmap))484		return PTR_ERR(regmap);485 486	return ad5380_probe(&spi->dev, regmap, id->driver_data, id->name);487}488 489static void ad5380_spi_remove(struct spi_device *spi)490{491	ad5380_remove(&spi->dev);492}493 494static const struct spi_device_id ad5380_spi_ids[] = {495	{ "ad5380-3", ID_AD5380_3 },496	{ "ad5380-5", ID_AD5380_5 },497	{ "ad5381-3", ID_AD5381_3 },498	{ "ad5381-5", ID_AD5381_5 },499	{ "ad5382-3", ID_AD5382_3 },500	{ "ad5382-5", ID_AD5382_5 },501	{ "ad5383-3", ID_AD5383_3 },502	{ "ad5383-5", ID_AD5383_5 },503	{ "ad5384-3", ID_AD5380_3 },504	{ "ad5384-5", ID_AD5380_5 },505	{ "ad5390-3", ID_AD5390_3 },506	{ "ad5390-5", ID_AD5390_5 },507	{ "ad5391-3", ID_AD5391_3 },508	{ "ad5391-5", ID_AD5391_5 },509	{ "ad5392-3", ID_AD5392_3 },510	{ "ad5392-5", ID_AD5392_5 },511	{ }512};513MODULE_DEVICE_TABLE(spi, ad5380_spi_ids);514 515static struct spi_driver ad5380_spi_driver = {516	.driver = {517		   .name = "ad5380",518	},519	.probe = ad5380_spi_probe,520	.remove = ad5380_spi_remove,521	.id_table = ad5380_spi_ids,522};523 524static inline int ad5380_spi_register_driver(void)525{526	return spi_register_driver(&ad5380_spi_driver);527}528 529static inline void ad5380_spi_unregister_driver(void)530{531	spi_unregister_driver(&ad5380_spi_driver);532}533 534#else535 536static inline int ad5380_spi_register_driver(void)537{538	return 0;539}540 541static inline void ad5380_spi_unregister_driver(void)542{543}544 545#endif546 547#if IS_ENABLED(CONFIG_I2C)548 549static int ad5380_i2c_probe(struct i2c_client *i2c)550{551	const struct i2c_device_id *id = i2c_client_get_device_id(i2c);552	struct regmap *regmap;553 554	regmap = devm_regmap_init_i2c(i2c, &ad5380_regmap_config);555 556	if (IS_ERR(regmap))557		return PTR_ERR(regmap);558 559	return ad5380_probe(&i2c->dev, regmap, id->driver_data, id->name);560}561 562static void ad5380_i2c_remove(struct i2c_client *i2c)563{564	ad5380_remove(&i2c->dev);565}566 567static const struct i2c_device_id ad5380_i2c_ids[] = {568	{ "ad5380-3", ID_AD5380_3 },569	{ "ad5380-5", ID_AD5380_5 },570	{ "ad5381-3", ID_AD5381_3 },571	{ "ad5381-5", ID_AD5381_5 },572	{ "ad5382-3", ID_AD5382_3 },573	{ "ad5382-5", ID_AD5382_5 },574	{ "ad5383-3", ID_AD5383_3 },575	{ "ad5383-5", ID_AD5383_5 },576	{ "ad5384-3", ID_AD5380_3 },577	{ "ad5384-5", ID_AD5380_5 },578	{ "ad5390-3", ID_AD5390_3 },579	{ "ad5390-5", ID_AD5390_5 },580	{ "ad5391-3", ID_AD5391_3 },581	{ "ad5391-5", ID_AD5391_5 },582	{ "ad5392-3", ID_AD5392_3 },583	{ "ad5392-5", ID_AD5392_5 },584	{ }585};586MODULE_DEVICE_TABLE(i2c, ad5380_i2c_ids);587 588static struct i2c_driver ad5380_i2c_driver = {589	.driver = {590		   .name = "ad5380",591	},592	.probe = ad5380_i2c_probe,593	.remove = ad5380_i2c_remove,594	.id_table = ad5380_i2c_ids,595};596 597static inline int ad5380_i2c_register_driver(void)598{599	return i2c_add_driver(&ad5380_i2c_driver);600}601 602static inline void ad5380_i2c_unregister_driver(void)603{604	i2c_del_driver(&ad5380_i2c_driver);605}606 607#else608 609static inline int ad5380_i2c_register_driver(void)610{611	return 0;612}613 614static inline void ad5380_i2c_unregister_driver(void)615{616}617 618#endif619 620static int __init ad5380_spi_init(void)621{622	int ret;623 624	ret = ad5380_spi_register_driver();625	if (ret)626		return ret;627 628	ret = ad5380_i2c_register_driver();629	if (ret) {630		ad5380_spi_unregister_driver();631		return ret;632	}633 634	return 0;635}636module_init(ad5380_spi_init);637 638static void __exit ad5380_spi_exit(void)639{640	ad5380_i2c_unregister_driver();641	ad5380_spi_unregister_driver();642 643}644module_exit(ad5380_spi_exit);645 646MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");647MODULE_DESCRIPTION("Analog Devices AD5380/81/82/83/84/90/91/92 DAC");648MODULE_LICENSE("GPL v2");649