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