ad5791.c 11.0 KB
Newer Older
1
/*
2 3
 * AD5760, AD5780, AD5781, AD5790, AD5791 Voltage Output Digital to Analog
 * Converter
4 5 6 7 8 9 10 11 12 13 14 15 16 17
 *
 * Copyright 2011 Analog Devices Inc.
 *
 * Licensed under the GPL-2.
 */

#include <linux/interrupt.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/spi/spi.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
#include <linux/regulator/consumer.h>
18
#include <linux/module.h>
19

20 21
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
22
#include <linux/iio/dac/ad5791.h>
23

24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
#define AD5791_RES_MASK(x)		((1 << (x)) - 1)
#define AD5791_DAC_MASK			AD5791_RES_MASK(20)
#define AD5791_DAC_MSB			(1 << 19)

#define AD5791_CMD_READ			(1 << 23)
#define AD5791_CMD_WRITE		(0 << 23)
#define AD5791_ADDR(addr)		((addr) << 20)

/* Registers */
#define AD5791_ADDR_NOOP		0
#define AD5791_ADDR_DAC0		1
#define AD5791_ADDR_CTRL		2
#define AD5791_ADDR_CLRCODE		3
#define AD5791_ADDR_SW_CTRL		4

/* Control Register */
#define AD5791_CTRL_RBUF		(1 << 1)
#define AD5791_CTRL_OPGND		(1 << 2)
#define AD5791_CTRL_DACTRI		(1 << 3)
#define AD5791_CTRL_BIN2SC		(1 << 4)
#define AD5791_CTRL_SDODIS		(1 << 5)
#define AD5761_CTRL_LINCOMP(x)		((x) << 6)

#define AD5791_LINCOMP_0_10		0
#define AD5791_LINCOMP_10_12		1
#define AD5791_LINCOMP_12_16		2
#define AD5791_LINCOMP_16_19		3
#define AD5791_LINCOMP_19_20		12

#define AD5780_LINCOMP_0_10		0
#define AD5780_LINCOMP_10_20		12

/* Software Control Register */
#define AD5791_SWCTRL_LDAC		(1 << 0)
#define AD5791_SWCTRL_CLR		(1 << 1)
#define AD5791_SWCTRL_RESET		(1 << 2)

#define AD5791_DAC_PWRDN_6K		0
#define AD5791_DAC_PWRDN_3STATE		1

/**
 * struct ad5791_chip_info - chip specific information
 * @get_lin_comp:	function pointer to the device specific function
 */

struct ad5791_chip_info {
	int (*get_lin_comp)	(unsigned int span);
};

/**
 * struct ad5791_state - driver instance specific data
 * @us:			spi_device
 * @reg_vdd:		positive supply regulator
 * @reg_vss:		negative supply regulator
 * @chip_info:		chip model specific constants
 * @vref_mv:		actual reference voltage used
 * @vref_neg_mv:	voltage of the negative supply
 * @pwr_down_mode	current power down mode
 */

struct ad5791_state {
	struct spi_device		*spi;
	struct regulator		*reg_vdd;
	struct regulator		*reg_vss;
	const struct ad5791_chip_info	*chip_info;
	unsigned short			vref_mv;
	unsigned int			vref_neg_mv;
	unsigned			ctrl;
	unsigned			pwr_down_mode;
	bool				pwr_down;
};

/**
 * ad5791_supported_device_ids:
 */

enum ad5791_supported_device_ids {
	ID_AD5760,
	ID_AD5780,
	ID_AD5781,
	ID_AD5791,
};

107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
static int ad5791_spi_write(struct spi_device *spi, u8 addr, u32 val)
{
	union {
		u32 d32;
		u8 d8[4];
	} data;

	data.d32 = cpu_to_be32(AD5791_CMD_WRITE |
			      AD5791_ADDR(addr) |
			      (val & AD5791_DAC_MASK));

	return spi_write(spi, &data.d8[1], 3);
}

static int ad5791_spi_read(struct spi_device *spi, u8 addr, u32 *val)
{
	union {
		u32 d32;
		u8 d8[4];
	} data[3];
	int ret;
	struct spi_transfer xfers[] = {
		{
			.tx_buf = &data[0].d8[1],
			.bits_per_word = 8,
			.len = 3,
			.cs_change = 1,
		}, {
			.tx_buf = &data[1].d8[1],
			.rx_buf = &data[2].d8[1],
			.bits_per_word = 8,
			.len = 3,
		},
	};

	data[0].d32 = cpu_to_be32(AD5791_CMD_READ |
			      AD5791_ADDR(addr));
	data[1].d32 = cpu_to_be32(AD5791_ADDR(AD5791_ADDR_NOOP));

146
	ret = spi_sync_transfer(spi, xfers, ARRAY_SIZE(xfers));
147 148 149 150 151 152

	*val = be32_to_cpu(data[2].d32);

	return ret;
}

153 154 155
static const char * const ad5791_powerdown_modes[] = {
	"6kohm_to_gnd",
	"three_state",
156
};
157

158 159
static int ad5791_get_powerdown_mode(struct iio_dev *indio_dev,
	const struct iio_chan_spec *chan)
160
{
161
	struct ad5791_state *st = iio_priv(indio_dev);
162

163
	return st->pwr_down_mode;
164 165
}

166 167
static int ad5791_set_powerdown_mode(struct iio_dev *indio_dev,
	const struct iio_chan_spec *chan, unsigned int mode)
168
{
169
	struct ad5791_state *st = iio_priv(indio_dev);
170

171
	st->pwr_down_mode = mode;
172

173
	return 0;
174 175
}

176 177 178 179 180 181 182 183 184
static const struct iio_enum ad5791_powerdown_mode_enum = {
	.items = ad5791_powerdown_modes,
	.num_items = ARRAY_SIZE(ad5791_powerdown_modes),
	.get = ad5791_get_powerdown_mode,
	.set = ad5791_set_powerdown_mode,
};

static ssize_t ad5791_read_dac_powerdown(struct iio_dev *indio_dev,
	uintptr_t private, const struct iio_chan_spec *chan, char *buf)
185
{
186
	struct ad5791_state *st = iio_priv(indio_dev);
187 188 189 190

	return sprintf(buf, "%d\n", st->pwr_down);
}

191 192 193
static ssize_t ad5791_write_dac_powerdown(struct iio_dev *indio_dev,
	 uintptr_t private, const struct iio_chan_spec *chan, const char *buf,
	 size_t len)
194
{
195
	bool pwr_down;
196
	int ret;
197
	struct ad5791_state *st = iio_priv(indio_dev);
198

199
	ret = strtobool(buf, &pwr_down);
200 201 202
	if (ret)
		return ret;

203
	if (!pwr_down) {
204
		st->ctrl &= ~(AD5791_CTRL_OPGND | AD5791_CTRL_DACTRI);
205
	} else {
206 207 208 209
		if (st->pwr_down_mode == AD5791_DAC_PWRDN_6K)
			st->ctrl |= AD5791_CTRL_OPGND;
		else if (st->pwr_down_mode == AD5791_DAC_PWRDN_3STATE)
			st->ctrl |= AD5791_CTRL_DACTRI;
210 211
	}
	st->pwr_down = pwr_down;
212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231

	ret = ad5791_spi_write(st->spi, AD5791_ADDR_CTRL, st->ctrl);

	return ret ? ret : len;
}

static int ad5791_get_lin_comp(unsigned int span)
{
	if (span <= 10000)
		return AD5791_LINCOMP_0_10;
	else if (span <= 12000)
		return AD5791_LINCOMP_10_12;
	else if (span <= 16000)
		return AD5791_LINCOMP_12_16;
	else if (span <= 19000)
		return AD5791_LINCOMP_16_19;
	else
		return AD5791_LINCOMP_19_20;
}

232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253
static int ad5780_get_lin_comp(unsigned int span)
{
	if (span <= 10000)
		return AD5780_LINCOMP_0_10;
	else
		return AD5780_LINCOMP_10_20;
}
static const struct ad5791_chip_info ad5791_chip_info_tbl[] = {
	[ID_AD5760] = {
		.get_lin_comp = ad5780_get_lin_comp,
	},
	[ID_AD5780] = {
		.get_lin_comp = ad5780_get_lin_comp,
	},
	[ID_AD5781] = {
		.get_lin_comp = ad5791_get_lin_comp,
	},
	[ID_AD5791] = {
		.get_lin_comp = ad5791_get_lin_comp,
	},
};

254 255 256 257 258 259 260
static int ad5791_read_raw(struct iio_dev *indio_dev,
			   struct iio_chan_spec const *chan,
			   int *val,
			   int *val2,
			   long m)
{
	struct ad5791_state *st = iio_priv(indio_dev);
261
	u64 val64;
262 263 264
	int ret;

	switch (m) {
265
	case IIO_CHAN_INFO_RAW:
266 267 268 269 270 271
		ret = ad5791_spi_read(st->spi, chan->address, val);
		if (ret)
			return ret;
		*val &= AD5791_DAC_MASK;
		*val >>= chan->scan_type.shift;
		return IIO_VAL_INT;
272
	case IIO_CHAN_INFO_SCALE:
273
		*val = 0;
274
		*val2 = (((u64)st->vref_mv) * 1000000ULL) >> chan->scan_type.realbits;
275
		return IIO_VAL_INT_PLUS_MICRO;
276
	case IIO_CHAN_INFO_OFFSET:
277 278 279 280
		val64 = (((u64)st->vref_neg_mv) << chan->scan_type.realbits);
		do_div(val64, st->vref_mv);
		*val = -val64;
		return IIO_VAL_INT;
281 282 283 284 285 286
	default:
		return -EINVAL;
	}

};

287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304
static const struct iio_chan_spec_ext_info ad5791_ext_info[] = {
	{
		.name = "powerdown",
		.shared = true,
		.read = ad5791_read_dac_powerdown,
		.write = ad5791_write_dac_powerdown,
	},
	IIO_ENUM("powerdown_mode", true, &ad5791_powerdown_mode_enum),
	IIO_ENUM_AVAILABLE("powerdown_mode", &ad5791_powerdown_mode_enum),
	{ },
};

#define AD5791_CHAN(bits, shift) {			\
	.type = IIO_VOLTAGE,				\
	.output = 1,					\
	.indexed = 1,					\
	.address = AD5791_ADDR_DAC0,			\
	.channel = 0,					\
305 306 307
	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),	\
	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |	\
		BIT(IIO_CHAN_INFO_OFFSET),		\
308 309 310 311 312 313 314 315 316 317
	.scan_type = IIO_ST('u', bits, 24, shift),	\
	.ext_info = ad5791_ext_info,			\
}

static const struct iio_chan_spec ad5791_channels[] = {
	[ID_AD5760] = AD5791_CHAN(16, 4),
	[ID_AD5780] = AD5791_CHAN(18, 2),
	[ID_AD5781] = AD5791_CHAN(18, 2),
	[ID_AD5791] = AD5791_CHAN(20, 0)
};
318 319 320 321 322 323 324 325 326 327

static int ad5791_write_raw(struct iio_dev *indio_dev,
			    struct iio_chan_spec const *chan,
			    int val,
			    int val2,
			    long mask)
{
	struct ad5791_state *st = iio_priv(indio_dev);

	switch (mask) {
328
	case IIO_CHAN_INFO_RAW:
329
		val &= AD5791_RES_MASK(chan->scan_type.realbits);
330 331 332 333 334 335 336 337 338
		val <<= chan->scan_type.shift;

		return ad5791_spi_write(st->spi, chan->address, val);

	default:
		return -EINVAL;
	}
}

339
static const struct iio_info ad5791_info = {
340 341
	.read_raw = &ad5791_read_raw,
	.write_raw = &ad5791_write_raw,
342 343 344
	.driver_module = THIS_MODULE,
};

345
static int ad5791_probe(struct spi_device *spi)
346 347
{
	struct ad5791_platform_data *pdata = spi->dev.platform_data;
348
	struct iio_dev *indio_dev;
349 350 351
	struct ad5791_state *st;
	int ret, pos_voltage_uv = 0, neg_voltage_uv = 0;

S
Sachin Kamat 已提交
352 353 354
	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
	if (!indio_dev)
		return -ENOMEM;
355
	st = iio_priv(indio_dev);
S
Sachin Kamat 已提交
356
	st->reg_vdd = devm_regulator_get(&spi->dev, "vdd");
357 358
	if (!IS_ERR(st->reg_vdd)) {
		ret = regulator_enable(st->reg_vdd);
359
		if (ret)
S
Sachin Kamat 已提交
360
			return ret;
361

362 363 364 365 366
		ret = regulator_get_voltage(st->reg_vdd);
		if (ret < 0)
			goto error_disable_reg_pos;

		pos_voltage_uv = ret;
367 368
	}

S
Sachin Kamat 已提交
369
	st->reg_vss = devm_regulator_get(&spi->dev, "vss");
370 371
	if (!IS_ERR(st->reg_vss)) {
		ret = regulator_enable(st->reg_vss);
372
		if (ret)
S
Sachin Kamat 已提交
373
			goto error_disable_reg_pos;
374

375 376 377 378 379
		ret = regulator_get_voltage(st->reg_vss);
		if (ret < 0)
			goto error_disable_reg_neg;

		neg_voltage_uv = ret;
380 381
	}

382 383 384
	st->pwr_down = true;
	st->spi = spi;

385 386 387 388 389 390 391
	if (!IS_ERR(st->reg_vss) && !IS_ERR(st->reg_vdd)) {
		st->vref_mv = (pos_voltage_uv + neg_voltage_uv) / 1000;
		st->vref_neg_mv = neg_voltage_uv / 1000;
	} else if (pdata) {
		st->vref_mv = pdata->vref_pos_mv + pdata->vref_neg_mv;
		st->vref_neg_mv = pdata->vref_neg_mv;
	} else {
392
		dev_warn(&spi->dev, "reference voltage unspecified\n");
393
	}
394 395 396

	ret = ad5791_spi_write(spi, AD5791_ADDR_SW_CTRL, AD5791_SWCTRL_RESET);
	if (ret)
397
		goto error_disable_reg_neg;
398

399 400
	st->chip_info =	&ad5791_chip_info_tbl[spi_get_device_id(spi)
					      ->driver_data];
401 402


403 404
	st->ctrl = AD5761_CTRL_LINCOMP(st->chip_info->get_lin_comp(st->vref_mv))
		  | ((pdata && pdata->use_rbuf_gain2) ? 0 : AD5791_CTRL_RBUF) |
405 406 407 408 409
		  AD5791_CTRL_BIN2SC;

	ret = ad5791_spi_write(spi, AD5791_ADDR_CTRL, st->ctrl |
		AD5791_CTRL_OPGND | AD5791_CTRL_DACTRI);
	if (ret)
410
		goto error_disable_reg_neg;
411

412 413 414 415
	spi_set_drvdata(spi, indio_dev);
	indio_dev->dev.parent = &spi->dev;
	indio_dev->info = &ad5791_info;
	indio_dev->modes = INDIO_DIRECT_MODE;
416 417 418 419
	indio_dev->channels
		= &ad5791_channels[spi_get_device_id(spi)->driver_data];
	indio_dev->num_channels = 1;
	indio_dev->name = spi_get_device_id(st->spi)->name;
420
	ret = iio_device_register(indio_dev);
421
	if (ret)
422
		goto error_disable_reg_neg;
423 424 425 426

	return 0;

error_disable_reg_neg:
427 428
	if (!IS_ERR(st->reg_vss))
		regulator_disable(st->reg_vss);
429
error_disable_reg_pos:
430 431
	if (!IS_ERR(st->reg_vdd))
		regulator_disable(st->reg_vdd);
432 433 434
	return ret;
}

435
static int ad5791_remove(struct spi_device *spi)
436
{
437 438
	struct iio_dev *indio_dev = spi_get_drvdata(spi);
	struct ad5791_state *st = iio_priv(indio_dev);
439

440
	iio_device_unregister(indio_dev);
S
Sachin Kamat 已提交
441
	if (!IS_ERR(st->reg_vdd))
442
		regulator_disable(st->reg_vdd);
443

S
Sachin Kamat 已提交
444
	if (!IS_ERR(st->reg_vss))
445
		regulator_disable(st->reg_vss);
446

447 448 449 450
	return 0;
}

static const struct spi_device_id ad5791_id[] = {
451 452
	{"ad5760", ID_AD5760},
	{"ad5780", ID_AD5780},
453
	{"ad5781", ID_AD5781},
454
	{"ad5790", ID_AD5791},
455
	{"ad5791", ID_AD5791},
456 457
	{}
};
458
MODULE_DEVICE_TABLE(spi, ad5791_id);
459 460 461 462 463 464 465

static struct spi_driver ad5791_driver = {
	.driver = {
		   .name = "ad5791",
		   .owner = THIS_MODULE,
		   },
	.probe = ad5791_probe,
466
	.remove = ad5791_remove,
467 468
	.id_table = ad5791_id,
};
469
module_spi_driver(ad5791_driver);
470 471

MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
472
MODULE_DESCRIPTION("Analog Devices AD5760/AD5780/AD5781/AD5790/AD5791 DAC");
473
MODULE_LICENSE("GPL v2");