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