169d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich/*
29d41c5bb07ad97b7777283d7922292f456ba4bfdLars-Peter Clausen * AD5760, AD5780, AD5781, AD5790, AD5791 Voltage Output Digital to Analog
39d41c5bb07ad97b7777283d7922292f456ba4bfdLars-Peter Clausen * Converter
469d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich *
569d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich * Copyright 2011 Analog Devices Inc.
669d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich *
769d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich * Licensed under the GPL-2.
869d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich */
969d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
1069d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich#include <linux/interrupt.h>
1169d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich#include <linux/fs.h>
1269d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich#include <linux/device.h>
1369d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich#include <linux/kernel.h>
1469d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich#include <linux/spi/spi.h>
1569d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich#include <linux/slab.h>
1669d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich#include <linux/sysfs.h>
1769d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich#include <linux/regulator/consumer.h>
1899c978529a40132a6f7a5f136b4362b56fc88d8cPaul Gortmaker#include <linux/module.h>
1969d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
2069d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich#include "../iio.h"
2169d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich#include "../sysfs.h"
2269d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich#include "dac.h"
2369d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich#include "ad5791.h"
2469d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
2569d900a69567b2cc217412e894a2c03218d23bebMichael Hennerichstatic int ad5791_spi_write(struct spi_device *spi, u8 addr, u32 val)
2669d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich{
2769d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	union {
2869d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich		u32 d32;
2969d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich		u8 d8[4];
3069d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	} data;
3169d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
3269d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	data.d32 = cpu_to_be32(AD5791_CMD_WRITE |
3369d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich			      AD5791_ADDR(addr) |
3469d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich			      (val & AD5791_DAC_MASK));
3569d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
3669d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	return spi_write(spi, &data.d8[1], 3);
3769d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich}
3869d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
3969d900a69567b2cc217412e894a2c03218d23bebMichael Hennerichstatic int ad5791_spi_read(struct spi_device *spi, u8 addr, u32 *val)
4069d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich{
4169d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	union {
4269d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich		u32 d32;
4369d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich		u8 d8[4];
4469d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	} data[3];
4569d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	int ret;
4669d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	struct spi_message msg;
4769d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	struct spi_transfer xfers[] = {
4869d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich		{
4969d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich			.tx_buf = &data[0].d8[1],
5069d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich			.bits_per_word = 8,
5169d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich			.len = 3,
5269d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich			.cs_change = 1,
5369d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich		}, {
5469d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich			.tx_buf = &data[1].d8[1],
5569d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich			.rx_buf = &data[2].d8[1],
5669d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich			.bits_per_word = 8,
5769d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich			.len = 3,
5869d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich		},
5969d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	};
6069d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
6169d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	data[0].d32 = cpu_to_be32(AD5791_CMD_READ |
6269d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich			      AD5791_ADDR(addr));
6369d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	data[1].d32 = cpu_to_be32(AD5791_ADDR(AD5791_ADDR_NOOP));
6469d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
6569d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	spi_message_init(&msg);
6669d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	spi_message_add_tail(&xfers[0], &msg);
6769d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	spi_message_add_tail(&xfers[1], &msg);
6869d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	ret = spi_sync(spi, &msg);
6969d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
7069d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	*val = be32_to_cpu(data[2].d32);
7169d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
7269d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	return ret;
7369d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich}
7469d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
75c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron#define AD5791_CHAN(bits, shift) {			\
76c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron	.type = IIO_VOLTAGE,				\
77c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron	.output = 1,					\
78c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron	.indexed = 1,					\
79c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron	.address = AD5791_ADDR_DAC0,			\
80c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron	.channel = 0,					\
81c8a9f8056f40f6201b84fdddb49a1c62630902c5Jonathan Cameron	.info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT | \
82c8a9f8056f40f6201b84fdddb49a1c62630902c5Jonathan Cameron		IIO_CHAN_INFO_OFFSET_SHARED_BIT,	\
83c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron	.scan_type = IIO_ST('u', bits, 24, shift)	\
8469d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich}
8569d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
86c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameronstatic const struct iio_chan_spec ad5791_channels[] = {
87c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron	[ID_AD5760] = AD5791_CHAN(16, 4),
88c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron	[ID_AD5780] = AD5791_CHAN(18, 2),
89c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron	[ID_AD5781] = AD5791_CHAN(18, 2),
90c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron	[ID_AD5791] = AD5791_CHAN(20, 0)
91c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron};
9269d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
9369d900a69567b2cc217412e894a2c03218d23bebMichael Hennerichstatic ssize_t ad5791_read_powerdown_mode(struct device *dev,
9469d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich				      struct device_attribute *attr, char *buf)
9569d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich{
9669d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	struct iio_dev *indio_dev = dev_get_drvdata(dev);
97f5730d52ba97cf58e4468b46ebbb49d704e23d20Jonathan Cameron	struct ad5791_state *st = iio_priv(indio_dev);
9869d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
9969d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	const char mode[][14] = {"6kohm_to_gnd", "three_state"};
10069d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
10169d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	return sprintf(buf, "%s\n", mode[st->pwr_down_mode]);
10269d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich}
10369d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
10469d900a69567b2cc217412e894a2c03218d23bebMichael Hennerichstatic ssize_t ad5791_write_powerdown_mode(struct device *dev,
10569d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich				       struct device_attribute *attr,
10669d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich				       const char *buf, size_t len)
10769d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich{
10869d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	struct iio_dev *indio_dev = dev_get_drvdata(dev);
109f5730d52ba97cf58e4468b46ebbb49d704e23d20Jonathan Cameron	struct ad5791_state *st = iio_priv(indio_dev);
11069d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	int ret;
11169d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
11269d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	if (sysfs_streq(buf, "6kohm_to_gnd"))
11369d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich		st->pwr_down_mode = AD5791_DAC_PWRDN_6K;
11469d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	else if (sysfs_streq(buf, "three_state"))
11569d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich		st->pwr_down_mode = AD5791_DAC_PWRDN_3STATE;
11669d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	else
11769d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich		ret = -EINVAL;
11869d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
11969d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	return ret ? ret : len;
12069d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich}
12169d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
12269d900a69567b2cc217412e894a2c03218d23bebMichael Hennerichstatic ssize_t ad5791_read_dac_powerdown(struct device *dev,
12369d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich					   struct device_attribute *attr,
12469d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich					   char *buf)
12569d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich{
12669d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	struct iio_dev *indio_dev = dev_get_drvdata(dev);
127f5730d52ba97cf58e4468b46ebbb49d704e23d20Jonathan Cameron	struct ad5791_state *st = iio_priv(indio_dev);
12869d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
12969d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	return sprintf(buf, "%d\n", st->pwr_down);
13069d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich}
13169d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
13269d900a69567b2cc217412e894a2c03218d23bebMichael Hennerichstatic ssize_t ad5791_write_dac_powerdown(struct device *dev,
13369d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich					    struct device_attribute *attr,
13469d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich					    const char *buf, size_t len)
13569d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich{
13669d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	long readin;
13769d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	int ret;
13869d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	struct iio_dev *indio_dev = dev_get_drvdata(dev);
139f5730d52ba97cf58e4468b46ebbb49d704e23d20Jonathan Cameron	struct ad5791_state *st = iio_priv(indio_dev);
14069d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
14169d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	ret = strict_strtol(buf, 10, &readin);
14269d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	if (ret)
14369d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich		return ret;
14469d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
14569d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	if (readin == 0) {
14669d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich		st->pwr_down = false;
14769d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich		st->ctrl &= ~(AD5791_CTRL_OPGND | AD5791_CTRL_DACTRI);
14869d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	} else if (readin == 1) {
14969d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich		st->pwr_down = true;
15069d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich		if (st->pwr_down_mode == AD5791_DAC_PWRDN_6K)
15169d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich			st->ctrl |= AD5791_CTRL_OPGND;
15269d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich		else if (st->pwr_down_mode == AD5791_DAC_PWRDN_3STATE)
15369d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich			st->ctrl |= AD5791_CTRL_DACTRI;
15469d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	} else
15569d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich		ret = -EINVAL;
15669d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
15769d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	ret = ad5791_spi_write(st->spi, AD5791_ADDR_CTRL, st->ctrl);
15869d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
15969d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	return ret ? ret : len;
16069d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich}
16169d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
162f1a61a8888afb9c21bb7efdd25f2755b01f065d3Lars-Peter Clausenstatic IIO_DEVICE_ATTR(out_voltage_powerdown_mode, S_IRUGO |
16369d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich			S_IWUSR, ad5791_read_powerdown_mode,
16469d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich			ad5791_write_powerdown_mode, 0);
16569d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
166f1a61a8888afb9c21bb7efdd25f2755b01f065d3Lars-Peter Clausenstatic IIO_CONST_ATTR(out_voltage_powerdown_mode_available,
16769d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich			"6kohm_to_gnd three_state");
16869d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
16969d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich#define IIO_DEV_ATTR_DAC_POWERDOWN(_num, _show, _store, _addr)		\
170f1a61a8888afb9c21bb7efdd25f2755b01f065d3Lars-Peter Clausen	IIO_DEVICE_ATTR(out_voltage##_num##_powerdown,			\
17169d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich			S_IRUGO | S_IWUSR, _show, _store, _addr)
17269d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
17369d900a69567b2cc217412e894a2c03218d23bebMichael Hennerichstatic IIO_DEV_ATTR_DAC_POWERDOWN(0, ad5791_read_dac_powerdown,
17469d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich				   ad5791_write_dac_powerdown, 0);
17569d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
17669d900a69567b2cc217412e894a2c03218d23bebMichael Hennerichstatic struct attribute *ad5791_attributes[] = {
177f1a61a8888afb9c21bb7efdd25f2755b01f065d3Lars-Peter Clausen	&iio_dev_attr_out_voltage0_powerdown.dev_attr.attr,
178f1a61a8888afb9c21bb7efdd25f2755b01f065d3Lars-Peter Clausen	&iio_dev_attr_out_voltage_powerdown_mode.dev_attr.attr,
179f1a61a8888afb9c21bb7efdd25f2755b01f065d3Lars-Peter Clausen	&iio_const_attr_out_voltage_powerdown_mode_available.dev_attr.attr,
18069d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	NULL,
18169d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich};
18269d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
18369d900a69567b2cc217412e894a2c03218d23bebMichael Hennerichstatic const struct attribute_group ad5791_attribute_group = {
18469d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	.attrs = ad5791_attributes,
18569d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich};
18669d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
18769d900a69567b2cc217412e894a2c03218d23bebMichael Hennerichstatic int ad5791_get_lin_comp(unsigned int span)
18869d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich{
18969d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	if (span <= 10000)
19069d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich		return AD5791_LINCOMP_0_10;
19169d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	else if (span <= 12000)
19269d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich		return AD5791_LINCOMP_10_12;
19369d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	else if (span <= 16000)
19469d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich		return AD5791_LINCOMP_12_16;
19569d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	else if (span <= 19000)
19669d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich		return AD5791_LINCOMP_16_19;
19769d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	else
19869d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich		return AD5791_LINCOMP_19_20;
19969d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich}
20069d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
201ba1c2bb2cc29eada78a6d35488291892431918e5Michael Hennerichstatic int ad5780_get_lin_comp(unsigned int span)
202ba1c2bb2cc29eada78a6d35488291892431918e5Michael Hennerich{
203ba1c2bb2cc29eada78a6d35488291892431918e5Michael Hennerich	if (span <= 10000)
204ba1c2bb2cc29eada78a6d35488291892431918e5Michael Hennerich		return AD5780_LINCOMP_0_10;
205ba1c2bb2cc29eada78a6d35488291892431918e5Michael Hennerich	else
206ba1c2bb2cc29eada78a6d35488291892431918e5Michael Hennerich		return AD5780_LINCOMP_10_20;
207ba1c2bb2cc29eada78a6d35488291892431918e5Michael Hennerich}
208ba1c2bb2cc29eada78a6d35488291892431918e5Michael Hennerichstatic const struct ad5791_chip_info ad5791_chip_info_tbl[] = {
209ba1c2bb2cc29eada78a6d35488291892431918e5Michael Hennerich	[ID_AD5760] = {
210ba1c2bb2cc29eada78a6d35488291892431918e5Michael Hennerich		.get_lin_comp = ad5780_get_lin_comp,
211ba1c2bb2cc29eada78a6d35488291892431918e5Michael Hennerich	},
212ba1c2bb2cc29eada78a6d35488291892431918e5Michael Hennerich	[ID_AD5780] = {
213ba1c2bb2cc29eada78a6d35488291892431918e5Michael Hennerich		.get_lin_comp = ad5780_get_lin_comp,
214ba1c2bb2cc29eada78a6d35488291892431918e5Michael Hennerich	},
215ba1c2bb2cc29eada78a6d35488291892431918e5Michael Hennerich	[ID_AD5781] = {
216ba1c2bb2cc29eada78a6d35488291892431918e5Michael Hennerich		.get_lin_comp = ad5791_get_lin_comp,
217ba1c2bb2cc29eada78a6d35488291892431918e5Michael Hennerich	},
218ba1c2bb2cc29eada78a6d35488291892431918e5Michael Hennerich	[ID_AD5791] = {
219ba1c2bb2cc29eada78a6d35488291892431918e5Michael Hennerich		.get_lin_comp = ad5791_get_lin_comp,
220ba1c2bb2cc29eada78a6d35488291892431918e5Michael Hennerich	},
221ba1c2bb2cc29eada78a6d35488291892431918e5Michael Hennerich};
222ba1c2bb2cc29eada78a6d35488291892431918e5Michael Hennerich
223c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameronstatic int ad5791_read_raw(struct iio_dev *indio_dev,
224c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron			   struct iio_chan_spec const *chan,
225c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron			   int *val,
226c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron			   int *val2,
227c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron			   long m)
228c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron{
229c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron	struct ad5791_state *st = iio_priv(indio_dev);
2309dc9961dca37379fd128508aac37e9f4928ee18fLars-Peter Clausen	u64 val64;
231c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron	int ret;
232c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron
233c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron	switch (m) {
234c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron	case 0:
235c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron		ret = ad5791_spi_read(st->spi, chan->address, val);
236c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron		if (ret)
237c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron			return ret;
238c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron		*val &= AD5791_DAC_MASK;
239c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron		*val >>= chan->scan_type.shift;
240c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron		return IIO_VAL_INT;
241c8a9f8056f40f6201b84fdddb49a1c62630902c5Jonathan Cameron	case IIO_CHAN_INFO_SCALE:
242c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron		*val = 0;
24375bb23a2150e385230d1db52065641ca7cef63d3Lars-Peter Clausen		*val2 = (((u64)st->vref_mv) * 1000000ULL) >> chan->scan_type.realbits;
244c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron		return IIO_VAL_INT_PLUS_MICRO;
245c8a9f8056f40f6201b84fdddb49a1c62630902c5Jonathan Cameron	case IIO_CHAN_INFO_OFFSET:
2469dc9961dca37379fd128508aac37e9f4928ee18fLars-Peter Clausen		val64 = (((u64)st->vref_neg_mv) << chan->scan_type.realbits);
2479dc9961dca37379fd128508aac37e9f4928ee18fLars-Peter Clausen		do_div(val64, st->vref_mv);
2489dc9961dca37379fd128508aac37e9f4928ee18fLars-Peter Clausen		*val = -val64;
2499dc9961dca37379fd128508aac37e9f4928ee18fLars-Peter Clausen		return IIO_VAL_INT;
250c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron	default:
251c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron		return -EINVAL;
252c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron	}
253c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron
254c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron};
255c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron
256c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron
257c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameronstatic int ad5791_write_raw(struct iio_dev *indio_dev,
258c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron			    struct iio_chan_spec const *chan,
259c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron			    int val,
260c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron			    int val2,
261c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron			    long mask)
262c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron{
263c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron	struct ad5791_state *st = iio_priv(indio_dev);
264c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron
265c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron	switch (mask) {
266c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron	case 0:
267021c0a381c5c1ae457bb9316669736d2ec66f972Lars-Peter Clausen		val &= AD5791_RES_MASK(chan->scan_type.realbits);
268c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron		val <<= chan->scan_type.shift;
269c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron
270c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron		return ad5791_spi_write(st->spi, chan->address, val);
271c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron
272c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron	default:
273c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron		return -EINVAL;
274c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron	}
275c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron}
276c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron
2776fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameronstatic const struct iio_info ad5791_info = {
278c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron	.read_raw = &ad5791_read_raw,
279c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron	.write_raw = &ad5791_write_raw,
2806fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron	.attrs = &ad5791_attribute_group,
2816fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron	.driver_module = THIS_MODULE,
2826fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron};
2836fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron
28469d900a69567b2cc217412e894a2c03218d23bebMichael Hennerichstatic int __devinit ad5791_probe(struct spi_device *spi)
28569d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich{
28669d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	struct ad5791_platform_data *pdata = spi->dev.platform_data;
287f5730d52ba97cf58e4468b46ebbb49d704e23d20Jonathan Cameron	struct iio_dev *indio_dev;
28869d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	struct ad5791_state *st;
28969d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	int ret, pos_voltage_uv = 0, neg_voltage_uv = 0;
29069d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
29126a54797c1b0941021a40a5973098fc28fe53d12Jonathan Cameron	indio_dev = iio_allocate_device(sizeof(*st));
29226a54797c1b0941021a40a5973098fc28fe53d12Jonathan Cameron	if (indio_dev == NULL) {
29326a54797c1b0941021a40a5973098fc28fe53d12Jonathan Cameron		ret = -ENOMEM;
29426a54797c1b0941021a40a5973098fc28fe53d12Jonathan Cameron		goto error_ret;
29526a54797c1b0941021a40a5973098fc28fe53d12Jonathan Cameron	}
29626a54797c1b0941021a40a5973098fc28fe53d12Jonathan Cameron	st = iio_priv(indio_dev);
29726a54797c1b0941021a40a5973098fc28fe53d12Jonathan Cameron	st->reg_vdd = regulator_get(&spi->dev, "vdd");
29826a54797c1b0941021a40a5973098fc28fe53d12Jonathan Cameron	if (!IS_ERR(st->reg_vdd)) {
29926a54797c1b0941021a40a5973098fc28fe53d12Jonathan Cameron		ret = regulator_enable(st->reg_vdd);
30069d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich		if (ret)
30169d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich			goto error_put_reg_pos;
30269d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
30326a54797c1b0941021a40a5973098fc28fe53d12Jonathan Cameron		pos_voltage_uv = regulator_get_voltage(st->reg_vdd);
30469d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	}
30569d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
30626a54797c1b0941021a40a5973098fc28fe53d12Jonathan Cameron	st->reg_vss = regulator_get(&spi->dev, "vss");
30726a54797c1b0941021a40a5973098fc28fe53d12Jonathan Cameron	if (!IS_ERR(st->reg_vss)) {
30826a54797c1b0941021a40a5973098fc28fe53d12Jonathan Cameron		ret = regulator_enable(st->reg_vss);
30969d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich		if (ret)
31069d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich			goto error_put_reg_neg;
31169d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
31226a54797c1b0941021a40a5973098fc28fe53d12Jonathan Cameron		neg_voltage_uv = regulator_get_voltage(st->reg_vss);
31369d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	}
31469d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
315f5730d52ba97cf58e4468b46ebbb49d704e23d20Jonathan Cameron	st->pwr_down = true;
316f5730d52ba97cf58e4468b46ebbb49d704e23d20Jonathan Cameron	st->spi = spi;
317f5730d52ba97cf58e4468b46ebbb49d704e23d20Jonathan Cameron
3189dc9961dca37379fd128508aac37e9f4928ee18fLars-Peter Clausen	if (!IS_ERR(st->reg_vss) && !IS_ERR(st->reg_vdd)) {
3199dc9961dca37379fd128508aac37e9f4928ee18fLars-Peter Clausen		st->vref_mv = (pos_voltage_uv + neg_voltage_uv) / 1000;
3209dc9961dca37379fd128508aac37e9f4928ee18fLars-Peter Clausen		st->vref_neg_mv = neg_voltage_uv / 1000;
3219dc9961dca37379fd128508aac37e9f4928ee18fLars-Peter Clausen	} else if (pdata) {
3229dc9961dca37379fd128508aac37e9f4928ee18fLars-Peter Clausen		st->vref_mv = pdata->vref_pos_mv + pdata->vref_neg_mv;
3239dc9961dca37379fd128508aac37e9f4928ee18fLars-Peter Clausen		st->vref_neg_mv = pdata->vref_neg_mv;
3249dc9961dca37379fd128508aac37e9f4928ee18fLars-Peter Clausen	} else {
32569d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich		dev_warn(&spi->dev, "reference voltage unspecified\n");
3269dc9961dca37379fd128508aac37e9f4928ee18fLars-Peter Clausen	}
32769d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
32869d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	ret = ad5791_spi_write(spi, AD5791_ADDR_SW_CTRL, AD5791_SWCTRL_RESET);
32969d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	if (ret)
33026a54797c1b0941021a40a5973098fc28fe53d12Jonathan Cameron		goto error_disable_reg_neg;
33169d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
332c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron	st->chip_info =	&ad5791_chip_info_tbl[spi_get_device_id(spi)
333c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron					      ->driver_data];
33469d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
33569d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
336ba1c2bb2cc29eada78a6d35488291892431918e5Michael Hennerich	st->ctrl = AD5761_CTRL_LINCOMP(st->chip_info->get_lin_comp(st->vref_mv))
337ba1c2bb2cc29eada78a6d35488291892431918e5Michael Hennerich		  | ((pdata && pdata->use_rbuf_gain2) ? 0 : AD5791_CTRL_RBUF) |
33869d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich		  AD5791_CTRL_BIN2SC;
33969d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
34069d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	ret = ad5791_spi_write(spi, AD5791_ADDR_CTRL, st->ctrl |
34169d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich		AD5791_CTRL_OPGND | AD5791_CTRL_DACTRI);
34269d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	if (ret)
34326a54797c1b0941021a40a5973098fc28fe53d12Jonathan Cameron		goto error_disable_reg_neg;
34469d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
345f5730d52ba97cf58e4468b46ebbb49d704e23d20Jonathan Cameron	spi_set_drvdata(spi, indio_dev);
346f5730d52ba97cf58e4468b46ebbb49d704e23d20Jonathan Cameron	indio_dev->dev.parent = &spi->dev;
347f5730d52ba97cf58e4468b46ebbb49d704e23d20Jonathan Cameron	indio_dev->info = &ad5791_info;
348f5730d52ba97cf58e4468b46ebbb49d704e23d20Jonathan Cameron	indio_dev->modes = INDIO_DIRECT_MODE;
349c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron	indio_dev->channels
350c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron		= &ad5791_channels[spi_get_device_id(spi)->driver_data];
351c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron	indio_dev->num_channels = 1;
352c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron	indio_dev->name = spi_get_device_id(st->spi)->name;
353f5730d52ba97cf58e4468b46ebbb49d704e23d20Jonathan Cameron	ret = iio_device_register(indio_dev);
35469d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	if (ret)
35526a54797c1b0941021a40a5973098fc28fe53d12Jonathan Cameron		goto error_disable_reg_neg;
35669d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
35769d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	return 0;
35869d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
35969d900a69567b2cc217412e894a2c03218d23bebMichael Hennericherror_disable_reg_neg:
36026a54797c1b0941021a40a5973098fc28fe53d12Jonathan Cameron	if (!IS_ERR(st->reg_vss))
36126a54797c1b0941021a40a5973098fc28fe53d12Jonathan Cameron		regulator_disable(st->reg_vss);
36269d900a69567b2cc217412e894a2c03218d23bebMichael Hennericherror_put_reg_neg:
36326a54797c1b0941021a40a5973098fc28fe53d12Jonathan Cameron	if (!IS_ERR(st->reg_vss))
36426a54797c1b0941021a40a5973098fc28fe53d12Jonathan Cameron		regulator_put(st->reg_vss);
36569d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
36626a54797c1b0941021a40a5973098fc28fe53d12Jonathan Cameron	if (!IS_ERR(st->reg_vdd))
36726a54797c1b0941021a40a5973098fc28fe53d12Jonathan Cameron		regulator_disable(st->reg_vdd);
36869d900a69567b2cc217412e894a2c03218d23bebMichael Hennericherror_put_reg_pos:
36926a54797c1b0941021a40a5973098fc28fe53d12Jonathan Cameron	if (!IS_ERR(st->reg_vdd))
37026a54797c1b0941021a40a5973098fc28fe53d12Jonathan Cameron		regulator_put(st->reg_vdd);
37126a54797c1b0941021a40a5973098fc28fe53d12Jonathan Cameron	iio_free_device(indio_dev);
37226a54797c1b0941021a40a5973098fc28fe53d12Jonathan Cameronerror_ret:
37369d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
37469d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	return ret;
37569d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich}
37669d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
37769d900a69567b2cc217412e894a2c03218d23bebMichael Hennerichstatic int __devexit ad5791_remove(struct spi_device *spi)
37869d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich{
379f5730d52ba97cf58e4468b46ebbb49d704e23d20Jonathan Cameron	struct iio_dev *indio_dev = spi_get_drvdata(spi);
380f5730d52ba97cf58e4468b46ebbb49d704e23d20Jonathan Cameron	struct ad5791_state *st = iio_priv(indio_dev);
38169d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
382d2fffd6c2fd60fe9ab63ef30758d9d43a5057549Jonathan Cameron	iio_device_unregister(indio_dev);
38369d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	if (!IS_ERR(st->reg_vdd)) {
38426a54797c1b0941021a40a5973098fc28fe53d12Jonathan Cameron		regulator_disable(st->reg_vdd);
38526a54797c1b0941021a40a5973098fc28fe53d12Jonathan Cameron		regulator_put(st->reg_vdd);
38669d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	}
38769d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
38869d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	if (!IS_ERR(st->reg_vss)) {
38926a54797c1b0941021a40a5973098fc28fe53d12Jonathan Cameron		regulator_disable(st->reg_vss);
39026a54797c1b0941021a40a5973098fc28fe53d12Jonathan Cameron		regulator_put(st->reg_vss);
39169d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	}
392d2fffd6c2fd60fe9ab63ef30758d9d43a5057549Jonathan Cameron	iio_free_device(indio_dev);
39326d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron
39469d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	return 0;
39569d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich}
39669d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
39769d900a69567b2cc217412e894a2c03218d23bebMichael Hennerichstatic const struct spi_device_id ad5791_id[] = {
398ba1c2bb2cc29eada78a6d35488291892431918e5Michael Hennerich	{"ad5760", ID_AD5760},
399ba1c2bb2cc29eada78a6d35488291892431918e5Michael Hennerich	{"ad5780", ID_AD5780},
40069d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	{"ad5781", ID_AD5781},
4019d41c5bb07ad97b7777283d7922292f456ba4bfdLars-Peter Clausen	{"ad5790", ID_AD5791},
402ba1c2bb2cc29eada78a6d35488291892431918e5Michael Hennerich	{"ad5791", ID_AD5791},
40369d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	{}
40469d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich};
40555e4390cb04e8b0fbae8983c3494c9e24132db1bLars-Peter ClausenMODULE_DEVICE_TABLE(spi, ad5791_id);
40669d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
40769d900a69567b2cc217412e894a2c03218d23bebMichael Hennerichstatic struct spi_driver ad5791_driver = {
40869d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	.driver = {
40969d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich		   .name = "ad5791",
41069d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich		   .owner = THIS_MODULE,
41169d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich		   },
41269d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	.probe = ad5791_probe,
41369d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	.remove = __devexit_p(ad5791_remove),
41469d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	.id_table = ad5791_id,
41569d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich};
416ae6ae6fec3f7d6919e0146996df37b665c75f662Lars-Peter Clausenmodule_spi_driver(ad5791_driver);
41769d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
41869d900a69567b2cc217412e894a2c03218d23bebMichael HennerichMODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
4199d41c5bb07ad97b7777283d7922292f456ba4bfdLars-Peter ClausenMODULE_DESCRIPTION("Analog Devices AD5760/AD5780/AD5781/AD5790/AD5791 DAC");
42069d900a69567b2cc217412e894a2c03218d23bebMichael HennerichMODULE_LICENSE("GPL v2");
421