ad5791.c revision d2fffd6c2fd60fe9ab63ef30758d9d43a5057549
169d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich/*
2ba1c2bb2cc29eada78a6d35488291892431918e5Michael Hennerich * AD5760, AD5780, AD5781, AD5791 Voltage Output Digital to Analog Converter
369d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich *
469d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich * Copyright 2011 Analog Devices Inc.
569d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich *
669d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich * Licensed under the GPL-2.
769d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich */
869d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
969d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich#include <linux/interrupt.h>
1069d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich#include <linux/fs.h>
1169d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich#include <linux/device.h>
1269d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich#include <linux/kernel.h>
1369d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich#include <linux/spi/spi.h>
1469d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich#include <linux/slab.h>
1569d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich#include <linux/sysfs.h>
1669d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich#include <linux/regulator/consumer.h>
1799c978529a40132a6f7a5f136b4362b56fc88d8cPaul Gortmaker#include <linux/module.h>
1869d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
1969d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich#include "../iio.h"
2069d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich#include "../sysfs.h"
2169d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich#include "dac.h"
2269d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich#include "ad5791.h"
2369d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
2469d900a69567b2cc217412e894a2c03218d23bebMichael Hennerichstatic int ad5791_spi_write(struct spi_device *spi, u8 addr, u32 val)
2569d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich{
2669d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	union {
2769d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich		u32 d32;
2869d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich		u8 d8[4];
2969d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	} data;
3069d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
3169d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	data.d32 = cpu_to_be32(AD5791_CMD_WRITE |
3269d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich			      AD5791_ADDR(addr) |
3369d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich			      (val & AD5791_DAC_MASK));
3469d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
3569d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	return spi_write(spi, &data.d8[1], 3);
3669d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich}
3769d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
3869d900a69567b2cc217412e894a2c03218d23bebMichael Hennerichstatic int ad5791_spi_read(struct spi_device *spi, u8 addr, u32 *val)
3969d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich{
4069d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	union {
4169d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich		u32 d32;
4269d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich		u8 d8[4];
4369d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	} data[3];
4469d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	int ret;
4569d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	struct spi_message msg;
4669d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	struct spi_transfer xfers[] = {
4769d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich		{
4869d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich			.tx_buf = &data[0].d8[1],
4969d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich			.bits_per_word = 8,
5069d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich			.len = 3,
5169d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich			.cs_change = 1,
5269d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich		}, {
5369d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich			.tx_buf = &data[1].d8[1],
5469d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich			.rx_buf = &data[2].d8[1],
5569d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich			.bits_per_word = 8,
5669d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich			.len = 3,
5769d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich		},
5869d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	};
5969d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
6069d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	data[0].d32 = cpu_to_be32(AD5791_CMD_READ |
6169d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich			      AD5791_ADDR(addr));
6269d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	data[1].d32 = cpu_to_be32(AD5791_ADDR(AD5791_ADDR_NOOP));
6369d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
6469d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	spi_message_init(&msg);
6569d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	spi_message_add_tail(&xfers[0], &msg);
6669d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	spi_message_add_tail(&xfers[1], &msg);
6769d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	ret = spi_sync(spi, &msg);
6869d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
6969d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	*val = be32_to_cpu(data[2].d32);
7069d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
7169d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	return ret;
7269d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich}
7369d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
74c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron#define AD5791_CHAN(bits, shift) {			\
75c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron	.type = IIO_VOLTAGE,				\
76c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron	.output = 1,					\
77c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron	.indexed = 1,					\
78c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron	.address = AD5791_ADDR_DAC0,			\
79c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron	.channel = 0,					\
80c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron	.info_mask = (1 << IIO_CHAN_INFO_SCALE_SHARED),	\
81c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron	.scan_type = IIO_ST('u', bits, 24, shift)	\
8269d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich}
8369d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
84c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameronstatic const struct iio_chan_spec ad5791_channels[] = {
85c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron	[ID_AD5760] = AD5791_CHAN(16, 4),
86c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron	[ID_AD5780] = AD5791_CHAN(18, 2),
87c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron	[ID_AD5781] = AD5791_CHAN(18, 2),
88c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron	[ID_AD5791] = AD5791_CHAN(20, 0)
89c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron};
9069d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
9169d900a69567b2cc217412e894a2c03218d23bebMichael Hennerichstatic ssize_t ad5791_read_powerdown_mode(struct device *dev,
9269d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich				      struct device_attribute *attr, char *buf)
9369d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich{
9469d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	struct iio_dev *indio_dev = dev_get_drvdata(dev);
95f5730d52ba97cf58e4468b46ebbb49d704e23d20Jonathan Cameron	struct ad5791_state *st = iio_priv(indio_dev);
9669d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
9769d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	const char mode[][14] = {"6kohm_to_gnd", "three_state"};
9869d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
9969d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	return sprintf(buf, "%s\n", mode[st->pwr_down_mode]);
10069d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich}
10169d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
10269d900a69567b2cc217412e894a2c03218d23bebMichael Hennerichstatic ssize_t ad5791_write_powerdown_mode(struct device *dev,
10369d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich				       struct device_attribute *attr,
10469d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich				       const char *buf, size_t len)
10569d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich{
10669d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	struct iio_dev *indio_dev = dev_get_drvdata(dev);
107f5730d52ba97cf58e4468b46ebbb49d704e23d20Jonathan Cameron	struct ad5791_state *st = iio_priv(indio_dev);
10869d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	int ret;
10969d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
11069d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	if (sysfs_streq(buf, "6kohm_to_gnd"))
11169d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich		st->pwr_down_mode = AD5791_DAC_PWRDN_6K;
11269d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	else if (sysfs_streq(buf, "three_state"))
11369d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich		st->pwr_down_mode = AD5791_DAC_PWRDN_3STATE;
11469d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	else
11569d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich		ret = -EINVAL;
11669d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
11769d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	return ret ? ret : len;
11869d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich}
11969d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
12069d900a69567b2cc217412e894a2c03218d23bebMichael Hennerichstatic ssize_t ad5791_read_dac_powerdown(struct device *dev,
12169d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich					   struct device_attribute *attr,
12269d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich					   char *buf)
12369d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich{
12469d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	struct iio_dev *indio_dev = dev_get_drvdata(dev);
125f5730d52ba97cf58e4468b46ebbb49d704e23d20Jonathan Cameron	struct ad5791_state *st = iio_priv(indio_dev);
12669d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
12769d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	return sprintf(buf, "%d\n", st->pwr_down);
12869d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich}
12969d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
13069d900a69567b2cc217412e894a2c03218d23bebMichael Hennerichstatic ssize_t ad5791_write_dac_powerdown(struct device *dev,
13169d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich					    struct device_attribute *attr,
13269d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich					    const char *buf, size_t len)
13369d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich{
13469d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	long readin;
13569d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	int ret;
13669d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	struct iio_dev *indio_dev = dev_get_drvdata(dev);
137f5730d52ba97cf58e4468b46ebbb49d704e23d20Jonathan Cameron	struct ad5791_state *st = iio_priv(indio_dev);
13869d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
13969d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	ret = strict_strtol(buf, 10, &readin);
14069d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	if (ret)
14169d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich		return ret;
14269d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
14369d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	if (readin == 0) {
14469d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich		st->pwr_down = false;
14569d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich		st->ctrl &= ~(AD5791_CTRL_OPGND | AD5791_CTRL_DACTRI);
14669d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	} else if (readin == 1) {
14769d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich		st->pwr_down = true;
14869d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich		if (st->pwr_down_mode == AD5791_DAC_PWRDN_6K)
14969d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich			st->ctrl |= AD5791_CTRL_OPGND;
15069d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich		else if (st->pwr_down_mode == AD5791_DAC_PWRDN_3STATE)
15169d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich			st->ctrl |= AD5791_CTRL_DACTRI;
15269d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	} else
15369d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich		ret = -EINVAL;
15469d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
15569d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	ret = ad5791_spi_write(st->spi, AD5791_ADDR_CTRL, st->ctrl);
15669d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
15769d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	return ret ? ret : len;
15869d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich}
15969d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
16069d900a69567b2cc217412e894a2c03218d23bebMichael Hennerichstatic IIO_DEVICE_ATTR(out_powerdown_mode, S_IRUGO |
16169d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich			S_IWUSR, ad5791_read_powerdown_mode,
16269d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich			ad5791_write_powerdown_mode, 0);
16369d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
16469d900a69567b2cc217412e894a2c03218d23bebMichael Hennerichstatic IIO_CONST_ATTR(out_powerdown_mode_available,
16569d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich			"6kohm_to_gnd three_state");
16669d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
16769d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich#define IIO_DEV_ATTR_DAC_POWERDOWN(_num, _show, _store, _addr)		\
16869d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	IIO_DEVICE_ATTR(out##_num##_powerdown,				\
16969d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich			S_IRUGO | S_IWUSR, _show, _store, _addr)
17069d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
17169d900a69567b2cc217412e894a2c03218d23bebMichael Hennerichstatic IIO_DEV_ATTR_DAC_POWERDOWN(0, ad5791_read_dac_powerdown,
17269d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich				   ad5791_write_dac_powerdown, 0);
17369d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
17469d900a69567b2cc217412e894a2c03218d23bebMichael Hennerichstatic struct attribute *ad5791_attributes[] = {
17569d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	&iio_dev_attr_out0_powerdown.dev_attr.attr,
17669d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	&iio_dev_attr_out_powerdown_mode.dev_attr.attr,
17769d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	&iio_const_attr_out_powerdown_mode_available.dev_attr.attr,
17869d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	NULL,
17969d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich};
18069d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
18169d900a69567b2cc217412e894a2c03218d23bebMichael Hennerichstatic const struct attribute_group ad5791_attribute_group = {
18269d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	.attrs = ad5791_attributes,
18369d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich};
18469d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
18569d900a69567b2cc217412e894a2c03218d23bebMichael Hennerichstatic int ad5791_get_lin_comp(unsigned int span)
18669d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich{
18769d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	if (span <= 10000)
18869d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich		return AD5791_LINCOMP_0_10;
18969d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	else if (span <= 12000)
19069d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich		return AD5791_LINCOMP_10_12;
19169d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	else if (span <= 16000)
19269d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich		return AD5791_LINCOMP_12_16;
19369d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	else if (span <= 19000)
19469d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich		return AD5791_LINCOMP_16_19;
19569d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	else
19669d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich		return AD5791_LINCOMP_19_20;
19769d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich}
19869d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
199ba1c2bb2cc29eada78a6d35488291892431918e5Michael Hennerichstatic int ad5780_get_lin_comp(unsigned int span)
200ba1c2bb2cc29eada78a6d35488291892431918e5Michael Hennerich{
201ba1c2bb2cc29eada78a6d35488291892431918e5Michael Hennerich	if (span <= 10000)
202ba1c2bb2cc29eada78a6d35488291892431918e5Michael Hennerich		return AD5780_LINCOMP_0_10;
203ba1c2bb2cc29eada78a6d35488291892431918e5Michael Hennerich	else
204ba1c2bb2cc29eada78a6d35488291892431918e5Michael Hennerich		return AD5780_LINCOMP_10_20;
205ba1c2bb2cc29eada78a6d35488291892431918e5Michael Hennerich}
206ba1c2bb2cc29eada78a6d35488291892431918e5Michael Hennerichstatic const struct ad5791_chip_info ad5791_chip_info_tbl[] = {
207ba1c2bb2cc29eada78a6d35488291892431918e5Michael Hennerich	[ID_AD5760] = {
208ba1c2bb2cc29eada78a6d35488291892431918e5Michael Hennerich		.get_lin_comp = ad5780_get_lin_comp,
209ba1c2bb2cc29eada78a6d35488291892431918e5Michael Hennerich	},
210ba1c2bb2cc29eada78a6d35488291892431918e5Michael Hennerich	[ID_AD5780] = {
211ba1c2bb2cc29eada78a6d35488291892431918e5Michael Hennerich		.get_lin_comp = ad5780_get_lin_comp,
212ba1c2bb2cc29eada78a6d35488291892431918e5Michael Hennerich	},
213ba1c2bb2cc29eada78a6d35488291892431918e5Michael Hennerich	[ID_AD5781] = {
214ba1c2bb2cc29eada78a6d35488291892431918e5Michael Hennerich		.get_lin_comp = ad5791_get_lin_comp,
215ba1c2bb2cc29eada78a6d35488291892431918e5Michael Hennerich	},
216ba1c2bb2cc29eada78a6d35488291892431918e5Michael Hennerich	[ID_AD5791] = {
217ba1c2bb2cc29eada78a6d35488291892431918e5Michael Hennerich		.get_lin_comp = ad5791_get_lin_comp,
218ba1c2bb2cc29eada78a6d35488291892431918e5Michael Hennerich	},
219ba1c2bb2cc29eada78a6d35488291892431918e5Michael Hennerich};
220ba1c2bb2cc29eada78a6d35488291892431918e5Michael Hennerich
221c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameronstatic int ad5791_read_raw(struct iio_dev *indio_dev,
222c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron			   struct iio_chan_spec const *chan,
223c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron			   int *val,
224c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron			   int *val2,
225c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron			   long m)
226c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron{
227c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron	struct ad5791_state *st = iio_priv(indio_dev);
228c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron	int ret;
229c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron
230c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron	switch (m) {
231c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron	case 0:
232c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron		ret = ad5791_spi_read(st->spi, chan->address, val);
233c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron		if (ret)
234c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron			return ret;
235c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron		*val &= AD5791_DAC_MASK;
236c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron		*val >>= chan->scan_type.shift;
237c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron		*val -= (1 << (chan->scan_type.storagebits - 1));
238c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron		return IIO_VAL_INT;
239c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron	case (1 << IIO_CHAN_INFO_SCALE_SHARED):
240c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron		*val = 0;
241c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron		*val2 = (st->vref_mv * 1000) >> chan->scan_type.storagebits;
242c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron		return IIO_VAL_INT_PLUS_MICRO;
243c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron	default:
244c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron		return -EINVAL;
245c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron	}
246c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron
247c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron};
248c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron
249c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron
250c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameronstatic int ad5791_write_raw(struct iio_dev *indio_dev,
251c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron			    struct iio_chan_spec const *chan,
252c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron			    int val,
253c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron			    int val2,
254c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron			    long mask)
255c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron{
256c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron	struct ad5791_state *st = iio_priv(indio_dev);
257c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron
258c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron	switch (mask) {
259c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron	case 0:
260c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron		val += (1 << (chan->scan_type.storagebits - 1));
261c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron		val &= AD5791_RES_MASK(chan->scan_type.storagebits);
262c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron		val <<= chan->scan_type.shift;
263c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron
264c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron		return ad5791_spi_write(st->spi, chan->address, val);
265c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron
266c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron	default:
267c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron		return -EINVAL;
268c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron	}
269c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron}
270c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron
2716fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameronstatic const struct iio_info ad5791_info = {
272c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron	.read_raw = &ad5791_read_raw,
273c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron	.write_raw = &ad5791_write_raw,
2746fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron	.attrs = &ad5791_attribute_group,
2756fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron	.driver_module = THIS_MODULE,
2766fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron};
2776fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron
27869d900a69567b2cc217412e894a2c03218d23bebMichael Hennerichstatic int __devinit ad5791_probe(struct spi_device *spi)
27969d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich{
28069d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	struct ad5791_platform_data *pdata = spi->dev.platform_data;
281f5730d52ba97cf58e4468b46ebbb49d704e23d20Jonathan Cameron	struct iio_dev *indio_dev;
28269d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	struct ad5791_state *st;
28369d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	int ret, pos_voltage_uv = 0, neg_voltage_uv = 0;
28469d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
28526a54797c1b0941021a40a5973098fc28fe53d12Jonathan Cameron	indio_dev = iio_allocate_device(sizeof(*st));
28626a54797c1b0941021a40a5973098fc28fe53d12Jonathan Cameron	if (indio_dev == NULL) {
28726a54797c1b0941021a40a5973098fc28fe53d12Jonathan Cameron		ret = -ENOMEM;
28826a54797c1b0941021a40a5973098fc28fe53d12Jonathan Cameron		goto error_ret;
28926a54797c1b0941021a40a5973098fc28fe53d12Jonathan Cameron	}
29026a54797c1b0941021a40a5973098fc28fe53d12Jonathan Cameron	st = iio_priv(indio_dev);
29126a54797c1b0941021a40a5973098fc28fe53d12Jonathan Cameron	st->reg_vdd = regulator_get(&spi->dev, "vdd");
29226a54797c1b0941021a40a5973098fc28fe53d12Jonathan Cameron	if (!IS_ERR(st->reg_vdd)) {
29326a54797c1b0941021a40a5973098fc28fe53d12Jonathan Cameron		ret = regulator_enable(st->reg_vdd);
29469d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich		if (ret)
29569d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich			goto error_put_reg_pos;
29669d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
29726a54797c1b0941021a40a5973098fc28fe53d12Jonathan Cameron		pos_voltage_uv = regulator_get_voltage(st->reg_vdd);
29869d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	}
29969d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
30026a54797c1b0941021a40a5973098fc28fe53d12Jonathan Cameron	st->reg_vss = regulator_get(&spi->dev, "vss");
30126a54797c1b0941021a40a5973098fc28fe53d12Jonathan Cameron	if (!IS_ERR(st->reg_vss)) {
30226a54797c1b0941021a40a5973098fc28fe53d12Jonathan Cameron		ret = regulator_enable(st->reg_vss);
30369d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich		if (ret)
30469d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich			goto error_put_reg_neg;
30569d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
30626a54797c1b0941021a40a5973098fc28fe53d12Jonathan Cameron		neg_voltage_uv = regulator_get_voltage(st->reg_vss);
30769d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	}
30869d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
309f5730d52ba97cf58e4468b46ebbb49d704e23d20Jonathan Cameron	st->pwr_down = true;
310f5730d52ba97cf58e4468b46ebbb49d704e23d20Jonathan Cameron	st->spi = spi;
311f5730d52ba97cf58e4468b46ebbb49d704e23d20Jonathan Cameron
31226a54797c1b0941021a40a5973098fc28fe53d12Jonathan Cameron	if (!IS_ERR(st->reg_vss) && !IS_ERR(st->reg_vdd))
31369d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich		st->vref_mv = (pos_voltage_uv - neg_voltage_uv) / 1000;
31469d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	else if (pdata)
31569d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich		st->vref_mv = pdata->vref_pos_mv - pdata->vref_neg_mv;
31669d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	else
31769d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich		dev_warn(&spi->dev, "reference voltage unspecified\n");
31869d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
31969d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	ret = ad5791_spi_write(spi, AD5791_ADDR_SW_CTRL, AD5791_SWCTRL_RESET);
32069d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	if (ret)
32126a54797c1b0941021a40a5973098fc28fe53d12Jonathan Cameron		goto error_disable_reg_neg;
32269d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
323c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron	st->chip_info =	&ad5791_chip_info_tbl[spi_get_device_id(spi)
324c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron					      ->driver_data];
32569d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
32669d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
327ba1c2bb2cc29eada78a6d35488291892431918e5Michael Hennerich	st->ctrl = AD5761_CTRL_LINCOMP(st->chip_info->get_lin_comp(st->vref_mv))
328ba1c2bb2cc29eada78a6d35488291892431918e5Michael Hennerich		  | ((pdata && pdata->use_rbuf_gain2) ? 0 : AD5791_CTRL_RBUF) |
32969d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich		  AD5791_CTRL_BIN2SC;
33069d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
33169d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	ret = ad5791_spi_write(spi, AD5791_ADDR_CTRL, st->ctrl |
33269d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich		AD5791_CTRL_OPGND | AD5791_CTRL_DACTRI);
33369d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	if (ret)
33426a54797c1b0941021a40a5973098fc28fe53d12Jonathan Cameron		goto error_disable_reg_neg;
33569d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
336f5730d52ba97cf58e4468b46ebbb49d704e23d20Jonathan Cameron	spi_set_drvdata(spi, indio_dev);
337f5730d52ba97cf58e4468b46ebbb49d704e23d20Jonathan Cameron	indio_dev->dev.parent = &spi->dev;
338f5730d52ba97cf58e4468b46ebbb49d704e23d20Jonathan Cameron	indio_dev->info = &ad5791_info;
339f5730d52ba97cf58e4468b46ebbb49d704e23d20Jonathan Cameron	indio_dev->modes = INDIO_DIRECT_MODE;
340c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron	indio_dev->channels
341c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron		= &ad5791_channels[spi_get_device_id(spi)->driver_data];
342c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron	indio_dev->num_channels = 1;
343c5b99396c70a1287bd49813121da37a828f69d23Jonathan Cameron	indio_dev->name = spi_get_device_id(st->spi)->name;
344f5730d52ba97cf58e4468b46ebbb49d704e23d20Jonathan Cameron	ret = iio_device_register(indio_dev);
34569d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	if (ret)
34626a54797c1b0941021a40a5973098fc28fe53d12Jonathan Cameron		goto error_disable_reg_neg;
34769d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
34869d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	return 0;
34969d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
35069d900a69567b2cc217412e894a2c03218d23bebMichael Hennericherror_disable_reg_neg:
35126a54797c1b0941021a40a5973098fc28fe53d12Jonathan Cameron	if (!IS_ERR(st->reg_vss))
35226a54797c1b0941021a40a5973098fc28fe53d12Jonathan Cameron		regulator_disable(st->reg_vss);
35369d900a69567b2cc217412e894a2c03218d23bebMichael Hennericherror_put_reg_neg:
35426a54797c1b0941021a40a5973098fc28fe53d12Jonathan Cameron	if (!IS_ERR(st->reg_vss))
35526a54797c1b0941021a40a5973098fc28fe53d12Jonathan Cameron		regulator_put(st->reg_vss);
35669d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
35726a54797c1b0941021a40a5973098fc28fe53d12Jonathan Cameron	if (!IS_ERR(st->reg_vdd))
35826a54797c1b0941021a40a5973098fc28fe53d12Jonathan Cameron		regulator_disable(st->reg_vdd);
35969d900a69567b2cc217412e894a2c03218d23bebMichael Hennericherror_put_reg_pos:
36026a54797c1b0941021a40a5973098fc28fe53d12Jonathan Cameron	if (!IS_ERR(st->reg_vdd))
36126a54797c1b0941021a40a5973098fc28fe53d12Jonathan Cameron		regulator_put(st->reg_vdd);
36226a54797c1b0941021a40a5973098fc28fe53d12Jonathan Cameron	iio_free_device(indio_dev);
36326a54797c1b0941021a40a5973098fc28fe53d12Jonathan Cameronerror_ret:
36469d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
36569d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	return ret;
36669d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich}
36769d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
36869d900a69567b2cc217412e894a2c03218d23bebMichael Hennerichstatic int __devexit ad5791_remove(struct spi_device *spi)
36969d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich{
370f5730d52ba97cf58e4468b46ebbb49d704e23d20Jonathan Cameron	struct iio_dev *indio_dev = spi_get_drvdata(spi);
371f5730d52ba97cf58e4468b46ebbb49d704e23d20Jonathan Cameron	struct ad5791_state *st = iio_priv(indio_dev);
37269d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
373d2fffd6c2fd60fe9ab63ef30758d9d43a5057549Jonathan Cameron	iio_device_unregister(indio_dev);
37469d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	if (!IS_ERR(st->reg_vdd)) {
37526a54797c1b0941021a40a5973098fc28fe53d12Jonathan Cameron		regulator_disable(st->reg_vdd);
37626a54797c1b0941021a40a5973098fc28fe53d12Jonathan Cameron		regulator_put(st->reg_vdd);
37769d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	}
37869d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
37969d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	if (!IS_ERR(st->reg_vss)) {
38026a54797c1b0941021a40a5973098fc28fe53d12Jonathan Cameron		regulator_disable(st->reg_vss);
38126a54797c1b0941021a40a5973098fc28fe53d12Jonathan Cameron		regulator_put(st->reg_vss);
38269d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	}
383d2fffd6c2fd60fe9ab63ef30758d9d43a5057549Jonathan Cameron	iio_free_device(indio_dev);
38426d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron
38569d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	return 0;
38669d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich}
38769d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
38869d900a69567b2cc217412e894a2c03218d23bebMichael Hennerichstatic const struct spi_device_id ad5791_id[] = {
389ba1c2bb2cc29eada78a6d35488291892431918e5Michael Hennerich	{"ad5760", ID_AD5760},
390ba1c2bb2cc29eada78a6d35488291892431918e5Michael Hennerich	{"ad5780", ID_AD5780},
39169d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	{"ad5781", ID_AD5781},
392ba1c2bb2cc29eada78a6d35488291892431918e5Michael Hennerich	{"ad5791", ID_AD5791},
39369d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	{}
39469d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich};
39569d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
39669d900a69567b2cc217412e894a2c03218d23bebMichael Hennerichstatic struct spi_driver ad5791_driver = {
39769d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	.driver = {
39869d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich		   .name = "ad5791",
39969d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich		   .owner = THIS_MODULE,
40069d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich		   },
40169d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	.probe = ad5791_probe,
40269d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	.remove = __devexit_p(ad5791_remove),
40369d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	.id_table = ad5791_id,
40469d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich};
40569d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
40669d900a69567b2cc217412e894a2c03218d23bebMichael Hennerichstatic __init int ad5791_spi_init(void)
40769d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich{
40869d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	return spi_register_driver(&ad5791_driver);
40969d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich}
41069d900a69567b2cc217412e894a2c03218d23bebMichael Hennerichmodule_init(ad5791_spi_init);
41169d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
41269d900a69567b2cc217412e894a2c03218d23bebMichael Hennerichstatic __exit void ad5791_spi_exit(void)
41369d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich{
41469d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich	spi_unregister_driver(&ad5791_driver);
41569d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich}
41669d900a69567b2cc217412e894a2c03218d23bebMichael Hennerichmodule_exit(ad5791_spi_exit);
41769d900a69567b2cc217412e894a2c03218d23bebMichael Hennerich
41869d900a69567b2cc217412e894a2c03218d23bebMichael HennerichMODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
419ba1c2bb2cc29eada78a6d35488291892431918e5Michael HennerichMODULE_DESCRIPTION("Analog Devices AD5760/AD5780/AD5781/AD5791 DAC");
42069d900a69567b2cc217412e894a2c03218d23bebMichael HennerichMODULE_LICENSE("GPL v2");
421