Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

iio:dac: Add support for the AD7303

This patch adds support for the AD7303. The AD7303 is a simple 2 channel 8 bit
DAC with an SPI interface.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Signed-off-by: Jonathan Cameron <jic23@kernel.org>

authored by

Lars-Peter Clausen and committed by
Jonathan Cameron
f8347824 e764df67

+370
+23
Documentation/devicetree/bindings/iio/dac/ad7303.txt
··· 1 + Analog Devices AD7303 DAC device driver 2 + 3 + Required properties: 4 + - compatible: Must be "adi,ad7303" 5 + - reg: SPI chip select number for the device 6 + - spi-max-frequency: Max SPI frequency to use (< 30000000) 7 + - Vdd-supply: Phandle to the Vdd power supply 8 + 9 + Optional properties: 10 + - REF-supply: Phandle to the external reference voltage supply. This should 11 + only be set if there is an external reference voltage connected to the REF 12 + pin. If the property is not set Vdd/2 is used as the reference voltage. 13 + 14 + Example: 15 + 16 + ad7303@4 { 17 + compatible = "adi,ad7303"; 18 + reg = <4>; 19 + spi-max-frequency = <10000000>; 20 + Vdd-supply = <&vdd_supply>; 21 + adi,use-external-reference; 22 + REF-supply = <&vref_supply>; 23 + };
+10
drivers/iio/dac/Kconfig
··· 130 130 To compile this driver as a module, choose M here: the 131 131 module will be called ad5686. 132 132 133 + config AD7303 134 + tristate "Analog Devices Analog Devices AD7303 DAC driver" 135 + depends on SPI 136 + help 137 + Say yes here to build support for Analog Devices AD7303 Digital to Analog 138 + Converters (DAC). 139 + 140 + To compile this driver as module choose M here: the module will be called 141 + ad7303. 142 + 133 143 config MAX517 134 144 tristate "Maxim MAX517/518/519 DAC driver" 135 145 depends on I2C
+1
drivers/iio/dac/Makefile
··· 14 14 obj-$(CONFIG_AD5764) += ad5764.o 15 15 obj-$(CONFIG_AD5791) += ad5791.o 16 16 obj-$(CONFIG_AD5686) += ad5686.o 17 + obj-$(CONFIG_AD7303) += ad7303.o 17 18 obj-$(CONFIG_MAX517) += max517.o 18 19 obj-$(CONFIG_MCP4725) += mcp4725.o
+315
drivers/iio/dac/ad7303.c
··· 1 + /* 2 + * AD7303 Digital to analog converters driver 3 + * 4 + * Copyright 2013 Analog Devices Inc. 5 + * 6 + * Licensed under the GPL-2. 7 + */ 8 + 9 + #include <linux/err.h> 10 + #include <linux/module.h> 11 + #include <linux/kernel.h> 12 + #include <linux/spi/spi.h> 13 + #include <linux/slab.h> 14 + #include <linux/sysfs.h> 15 + #include <linux/regulator/consumer.h> 16 + #include <linux/of.h> 17 + 18 + #include <linux/iio/iio.h> 19 + #include <linux/iio/sysfs.h> 20 + 21 + #include <linux/platform_data/ad7303.h> 22 + 23 + #define AD7303_CFG_EXTERNAL_VREF BIT(15) 24 + #define AD7303_CFG_POWER_DOWN(ch) BIT(11 + (ch)) 25 + #define AD7303_CFG_ADDR_OFFSET 10 26 + 27 + #define AD7303_CMD_UPDATE_DAC (0x3 << 8) 28 + 29 + /** 30 + * struct ad7303_state - driver instance specific data 31 + * @spi: the device for this driver instance 32 + * @config: cached config register value 33 + * @dac_cache: current DAC raw value (chip does not support readback) 34 + * @data: spi transfer buffer 35 + */ 36 + 37 + struct ad7303_state { 38 + struct spi_device *spi; 39 + uint16_t config; 40 + uint8_t dac_cache[2]; 41 + 42 + struct regulator *vdd_reg; 43 + struct regulator *vref_reg; 44 + 45 + /* 46 + * DMA (thus cache coherency maintenance) requires the 47 + * transfer buffers to live in their own cache lines. 48 + */ 49 + __be16 data ____cacheline_aligned; 50 + }; 51 + 52 + static int ad7303_write(struct ad7303_state *st, unsigned int chan, 53 + uint8_t val) 54 + { 55 + st->data = cpu_to_be16(AD7303_CMD_UPDATE_DAC | 56 + (chan << AD7303_CFG_ADDR_OFFSET) | 57 + st->config | val); 58 + 59 + return spi_write(st->spi, &st->data, sizeof(st->data)); 60 + } 61 + 62 + static ssize_t ad7303_read_dac_powerdown(struct iio_dev *indio_dev, 63 + uintptr_t private, const struct iio_chan_spec *chan, char *buf) 64 + { 65 + struct ad7303_state *st = iio_priv(indio_dev); 66 + 67 + return sprintf(buf, "%d\n", (bool)(st->config & 68 + AD7303_CFG_POWER_DOWN(chan->channel))); 69 + } 70 + 71 + static ssize_t ad7303_write_dac_powerdown(struct iio_dev *indio_dev, 72 + uintptr_t private, const struct iio_chan_spec *chan, const char *buf, 73 + size_t len) 74 + { 75 + struct ad7303_state *st = iio_priv(indio_dev); 76 + bool pwr_down; 77 + int ret; 78 + 79 + ret = strtobool(buf, &pwr_down); 80 + if (ret) 81 + return ret; 82 + 83 + mutex_lock(&indio_dev->mlock); 84 + 85 + if (pwr_down) 86 + st->config |= AD7303_CFG_POWER_DOWN(chan->channel); 87 + else 88 + st->config &= ~AD7303_CFG_POWER_DOWN(chan->channel); 89 + 90 + /* There is no noop cmd which allows us to only update the powerdown 91 + * mode, so just write one of the DAC channels again */ 92 + ad7303_write(st, chan->channel, st->dac_cache[chan->channel]); 93 + 94 + mutex_unlock(&indio_dev->mlock); 95 + return ret ? ret : len; 96 + } 97 + 98 + static int ad7303_get_vref(struct ad7303_state *st, 99 + struct iio_chan_spec const *chan) 100 + { 101 + int ret; 102 + 103 + if (st->config & AD7303_CFG_EXTERNAL_VREF) 104 + return regulator_get_voltage(st->vref_reg); 105 + 106 + ret = regulator_get_voltage(st->vdd_reg); 107 + if (ret < 0) 108 + return ret; 109 + return ret / 2; 110 + } 111 + 112 + static int ad7303_read_raw(struct iio_dev *indio_dev, 113 + struct iio_chan_spec const *chan, int *val, int *val2, long info) 114 + { 115 + struct ad7303_state *st = iio_priv(indio_dev); 116 + int vref_uv; 117 + 118 + switch (info) { 119 + case IIO_CHAN_INFO_RAW: 120 + *val = st->dac_cache[chan->channel]; 121 + return IIO_VAL_INT; 122 + case IIO_CHAN_INFO_SCALE: 123 + vref_uv = ad7303_get_vref(st, chan); 124 + if (vref_uv < 0) 125 + return vref_uv; 126 + 127 + *val = 2 * vref_uv / 1000; 128 + *val2 = chan->scan_type.realbits; 129 + 130 + return IIO_VAL_FRACTIONAL_LOG2; 131 + default: 132 + break; 133 + } 134 + return -EINVAL; 135 + } 136 + 137 + static int ad7303_write_raw(struct iio_dev *indio_dev, 138 + struct iio_chan_spec const *chan, int val, int val2, long mask) 139 + { 140 + struct ad7303_state *st = iio_priv(indio_dev); 141 + int ret; 142 + 143 + switch (mask) { 144 + case IIO_CHAN_INFO_RAW: 145 + if (val >= (1 << chan->scan_type.realbits) || val < 0) 146 + return -EINVAL; 147 + 148 + mutex_lock(&indio_dev->mlock); 149 + ret = ad7303_write(st, chan->address, val); 150 + if (ret == 0) 151 + st->dac_cache[chan->channel] = val; 152 + mutex_unlock(&indio_dev->mlock); 153 + break; 154 + default: 155 + ret = -EINVAL; 156 + } 157 + 158 + return ret; 159 + } 160 + 161 + static const struct iio_info ad7303_info = { 162 + .read_raw = ad7303_read_raw, 163 + .write_raw = ad7303_write_raw, 164 + .driver_module = THIS_MODULE, 165 + }; 166 + 167 + static const struct iio_chan_spec_ext_info ad7303_ext_info[] = { 168 + { 169 + .name = "powerdown", 170 + .read = ad7303_read_dac_powerdown, 171 + .write = ad7303_write_dac_powerdown, 172 + }, 173 + { }, 174 + }; 175 + 176 + #define AD7303_CHANNEL(chan) { \ 177 + .type = IIO_VOLTAGE, \ 178 + .indexed = 1, \ 179 + .output = 1, \ 180 + .channel = (chan), \ 181 + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ 182 + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ 183 + .address = (chan), \ 184 + .scan_type = { \ 185 + .sign = 'u', \ 186 + .realbits = '8', \ 187 + .storagebits = '8', \ 188 + .shift = '0', \ 189 + }, \ 190 + .ext_info = ad7303_ext_info, \ 191 + } 192 + 193 + static const struct iio_chan_spec ad7303_channels[] = { 194 + AD7303_CHANNEL(0), 195 + AD7303_CHANNEL(1), 196 + }; 197 + 198 + static int ad7303_probe(struct spi_device *spi) 199 + { 200 + const struct spi_device_id *id = spi_get_device_id(spi); 201 + struct iio_dev *indio_dev; 202 + struct ad7303_state *st; 203 + bool ext_ref; 204 + int ret; 205 + 206 + indio_dev = iio_device_alloc(sizeof(*st)); 207 + if (indio_dev == NULL) 208 + return -ENOMEM; 209 + 210 + st = iio_priv(indio_dev); 211 + spi_set_drvdata(spi, indio_dev); 212 + 213 + st->spi = spi; 214 + 215 + st->vdd_reg = regulator_get(&spi->dev, "Vdd"); 216 + if (IS_ERR(st->vdd_reg)) { 217 + ret = PTR_ERR(st->vdd_reg); 218 + goto err_free; 219 + } 220 + 221 + ret = regulator_enable(st->vdd_reg); 222 + if (ret) 223 + goto err_put_vdd_reg; 224 + 225 + if (spi->dev.of_node) { 226 + ext_ref = of_property_read_bool(spi->dev.of_node, 227 + "REF-supply"); 228 + } else { 229 + struct ad7303_platform_data *pdata = spi->dev.platform_data; 230 + if (pdata && pdata->use_external_ref) 231 + ext_ref = true; 232 + else 233 + ext_ref = false; 234 + } 235 + 236 + if (ext_ref) { 237 + st->vref_reg = regulator_get(&spi->dev, "REF"); 238 + if (IS_ERR(st->vref_reg)) 239 + goto err_disable_vdd_reg; 240 + 241 + ret = regulator_enable(st->vref_reg); 242 + if (ret) 243 + goto err_put_vref_reg; 244 + 245 + st->config |= AD7303_CFG_EXTERNAL_VREF; 246 + } 247 + 248 + indio_dev->dev.parent = &spi->dev; 249 + indio_dev->name = id->name; 250 + indio_dev->info = &ad7303_info; 251 + indio_dev->modes = INDIO_DIRECT_MODE; 252 + indio_dev->channels = ad7303_channels; 253 + indio_dev->num_channels = ARRAY_SIZE(ad7303_channels); 254 + 255 + ret = iio_device_register(indio_dev); 256 + if (ret) 257 + goto err_disable_vref_reg; 258 + 259 + return 0; 260 + 261 + err_disable_vref_reg: 262 + if (st->vref_reg) 263 + regulator_disable(st->vref_reg); 264 + err_put_vref_reg: 265 + if (st->vref_reg) 266 + regulator_put(st->vref_reg); 267 + err_disable_vdd_reg: 268 + regulator_disable(st->vdd_reg); 269 + err_put_vdd_reg: 270 + regulator_put(st->vdd_reg); 271 + err_free: 272 + iio_device_free(indio_dev); 273 + 274 + return ret; 275 + } 276 + 277 + static int ad7303_remove(struct spi_device *spi) 278 + { 279 + struct iio_dev *indio_dev = spi_get_drvdata(spi); 280 + struct ad7303_state *st = iio_priv(indio_dev); 281 + 282 + iio_device_unregister(indio_dev); 283 + 284 + if (st->vref_reg) { 285 + regulator_disable(st->vref_reg); 286 + regulator_put(st->vref_reg); 287 + } 288 + regulator_disable(st->vdd_reg); 289 + regulator_put(st->vdd_reg); 290 + 291 + iio_device_free(indio_dev); 292 + 293 + return 0; 294 + } 295 + 296 + static const struct spi_device_id ad7303_spi_ids[] = { 297 + { "ad7303", 0 }, 298 + {} 299 + }; 300 + MODULE_DEVICE_TABLE(spi, ad7303_spi_ids); 301 + 302 + static struct spi_driver ad7303_driver = { 303 + .driver = { 304 + .name = "ad7303", 305 + .owner = THIS_MODULE, 306 + }, 307 + .probe = ad7303_probe, 308 + .remove = ad7303_remove, 309 + .id_table = ad7303_spi_ids, 310 + }; 311 + module_spi_driver(ad7303_driver); 312 + 313 + MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); 314 + MODULE_DESCRIPTION("Analog Devices AD7303 DAC driver"); 315 + MODULE_LICENSE("GPL v2");
+21
include/linux/platform_data/ad7303.h
··· 1 + /* 2 + * Analog Devices AD7303 DAC driver 3 + * 4 + * Copyright 2013 Analog Devices Inc. 5 + * 6 + * Licensed under the GPL-2. 7 + */ 8 + 9 + #ifndef __IIO_ADC_AD7303_H__ 10 + #define __IIO_ADC_AD7303_H__ 11 + 12 + /** 13 + * struct ad7303_platform_data - AD7303 platform data 14 + * @use_external_ref: If set to true use an external voltage reference connected 15 + * to the REF pin, otherwise use the internal reference derived from Vdd. 16 + */ 17 + struct ad7303_platform_data { 18 + bool use_external_ref; 19 + }; 20 + 21 + #endif