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 ad5449

This patch adds support for the AD5415, AD5426, AD5429, AD5432, AD5439, AD5443
and AD5449 single and dual channel DACs.

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
8341dc04 103d9fb9

+426
+10
drivers/iio/dac/Kconfig
··· 67 67 To compile this driver as a module, choose M here: the 68 68 module will be called ad5446. 69 69 70 + config AD5449 71 + tristate "Analog Device AD5449 and similar DACs driver" 72 + depends on SPI_MASTER 73 + help 74 + Say yes here to build support for Analog Devices AD5415, AD5426, AD5429, 75 + AD5432, AD5439, AD5443, AD5449 Digital to Analog Converters. 76 + 77 + To compile this driver as a module, choose M here: the 78 + module will be called ad5449. 79 + 70 80 config AD5504 71 81 tristate "Analog Devices AD5504/AD5501 DAC SPI driver" 72 82 depends on SPI
+1
drivers/iio/dac/Makefile
··· 9 9 obj-$(CONFIG_AD5064) += ad5064.o 10 10 obj-$(CONFIG_AD5504) += ad5504.o 11 11 obj-$(CONFIG_AD5446) += ad5446.o 12 + obj-$(CONFIG_AD5449) += ad5449.o 12 13 obj-$(CONFIG_AD5755) += ad5755.o 13 14 obj-$(CONFIG_AD5764) += ad5764.o 14 15 obj-$(CONFIG_AD5791) += ad5791.o
+375
drivers/iio/dac/ad5449.c
··· 1 + /* 2 + * AD5415, AD5426, AD5429, AD5432, AD5439, AD5443, AD5449 Digital to Analog 3 + * Converter driver. 4 + * 5 + * Copyright 2012 Analog Devices Inc. 6 + * Author: Lars-Peter Clausen <lars@metafoo.de> 7 + * 8 + * Licensed under the GPL-2. 9 + */ 10 + 11 + #include <linux/device.h> 12 + #include <linux/err.h> 13 + #include <linux/module.h> 14 + #include <linux/kernel.h> 15 + #include <linux/spi/spi.h> 16 + #include <linux/slab.h> 17 + #include <linux/sysfs.h> 18 + #include <linux/regulator/consumer.h> 19 + #include <asm/unaligned.h> 20 + 21 + #include <linux/iio/iio.h> 22 + #include <linux/iio/sysfs.h> 23 + 24 + #include <linux/platform_data/ad5449.h> 25 + 26 + #define AD5449_MAX_CHANNELS 2 27 + #define AD5449_MAX_VREFS 2 28 + 29 + #define AD5449_CMD_NOOP 0x0 30 + #define AD5449_CMD_LOAD_AND_UPDATE(x) (0x1 + (x) * 3) 31 + #define AD5449_CMD_READ(x) (0x2 + (x) * 3) 32 + #define AD5449_CMD_LOAD(x) (0x3 + (x) * 3) 33 + #define AD5449_CMD_CTRL 13 34 + 35 + #define AD5449_CTRL_SDO_OFFSET 10 36 + #define AD5449_CTRL_DAISY_CHAIN BIT(9) 37 + #define AD5449_CTRL_HCLR_TO_MIDSCALE BIT(8) 38 + #define AD5449_CTRL_SAMPLE_RISING BIT(7) 39 + 40 + /** 41 + * struct ad5449_chip_info - chip specific information 42 + * @channels: Channel specification 43 + * @num_channels: Number of channels 44 + * @has_ctrl: Chip has a control register 45 + */ 46 + struct ad5449_chip_info { 47 + const struct iio_chan_spec *channels; 48 + unsigned int num_channels; 49 + bool has_ctrl; 50 + }; 51 + 52 + /** 53 + * struct ad5449 - driver instance specific data 54 + * @spi: the SPI device for this driver instance 55 + * @chip_info: chip model specific constants, available modes etc 56 + * @vref_reg: vref supply regulators 57 + * @has_sdo: whether the SDO line is connected 58 + * @dac_cache: Cache for the DAC values 59 + * @data: spi transfer buffers 60 + */ 61 + struct ad5449 { 62 + struct spi_device *spi; 63 + const struct ad5449_chip_info *chip_info; 64 + struct regulator_bulk_data vref_reg[AD5449_MAX_VREFS]; 65 + 66 + bool has_sdo; 67 + uint16_t dac_cache[AD5449_MAX_CHANNELS]; 68 + 69 + /* 70 + * DMA (thus cache coherency maintenance) requires the 71 + * transfer buffers to live in their own cache lines. 72 + */ 73 + __be16 data[2] ____cacheline_aligned; 74 + }; 75 + 76 + enum ad5449_type { 77 + ID_AD5426, 78 + ID_AD5429, 79 + ID_AD5432, 80 + ID_AD5439, 81 + ID_AD5443, 82 + ID_AD5449, 83 + }; 84 + 85 + static int ad5449_write(struct iio_dev *indio_dev, unsigned int addr, 86 + unsigned int val) 87 + { 88 + struct ad5449 *st = iio_priv(indio_dev); 89 + int ret; 90 + 91 + mutex_lock(&indio_dev->mlock); 92 + st->data[0] = cpu_to_be16((addr << 12) | val); 93 + ret = spi_write(st->spi, st->data, 2); 94 + mutex_unlock(&indio_dev->mlock); 95 + 96 + return ret; 97 + } 98 + 99 + static int ad5449_read(struct iio_dev *indio_dev, unsigned int addr, 100 + unsigned int *val) 101 + { 102 + struct ad5449 *st = iio_priv(indio_dev); 103 + int ret; 104 + struct spi_message msg; 105 + struct spi_transfer t[] = { 106 + { 107 + .tx_buf = &st->data[0], 108 + .len = 2, 109 + .cs_change = 1, 110 + }, { 111 + .tx_buf = &st->data[1], 112 + .rx_buf = &st->data[1], 113 + .len = 2, 114 + }, 115 + }; 116 + 117 + spi_message_init(&msg); 118 + spi_message_add_tail(&t[0], &msg); 119 + spi_message_add_tail(&t[1], &msg); 120 + 121 + mutex_lock(&indio_dev->mlock); 122 + st->data[0] = cpu_to_be16(addr << 12); 123 + st->data[1] = cpu_to_be16(AD5449_CMD_NOOP); 124 + 125 + ret = spi_sync(st->spi, &msg); 126 + if (ret < 0) 127 + return ret; 128 + 129 + *val = be16_to_cpu(st->data[1]); 130 + mutex_unlock(&indio_dev->mlock); 131 + 132 + return 0; 133 + } 134 + 135 + static int ad5449_read_raw(struct iio_dev *indio_dev, 136 + struct iio_chan_spec const *chan, int *val, int *val2, long info) 137 + { 138 + struct ad5449 *st = iio_priv(indio_dev); 139 + struct regulator_bulk_data *reg; 140 + int scale_uv; 141 + int ret; 142 + 143 + switch (info) { 144 + case IIO_CHAN_INFO_RAW: 145 + if (st->has_sdo) { 146 + ret = ad5449_read(indio_dev, 147 + AD5449_CMD_READ(chan->address), val); 148 + if (ret) 149 + return ret; 150 + *val &= 0xfff; 151 + } else { 152 + *val = st->dac_cache[chan->address]; 153 + } 154 + 155 + return IIO_VAL_INT; 156 + case IIO_CHAN_INFO_SCALE: 157 + reg = &st->vref_reg[chan->channel]; 158 + scale_uv = regulator_get_voltage(reg->consumer); 159 + if (scale_uv < 0) 160 + return scale_uv; 161 + 162 + *val = scale_uv / 1000; 163 + *val2 = chan->scan_type.realbits; 164 + 165 + return IIO_VAL_FRACTIONAL_LOG2; 166 + default: 167 + break; 168 + } 169 + 170 + return -EINVAL; 171 + } 172 + 173 + static int ad5449_write_raw(struct iio_dev *indio_dev, 174 + struct iio_chan_spec const *chan, int val, int val2, long info) 175 + { 176 + struct ad5449 *st = iio_priv(indio_dev); 177 + int ret; 178 + 179 + switch (info) { 180 + case IIO_CHAN_INFO_RAW: 181 + if (val < 0 || val >= (1 << chan->scan_type.realbits)) 182 + return -EINVAL; 183 + 184 + ret = ad5449_write(indio_dev, 185 + AD5449_CMD_LOAD_AND_UPDATE(chan->address), 186 + val << chan->scan_type.shift); 187 + if (ret == 0) 188 + st->dac_cache[chan->address] = val; 189 + break; 190 + default: 191 + ret = -EINVAL; 192 + } 193 + 194 + return ret; 195 + } 196 + 197 + static const struct iio_info ad5449_info = { 198 + .read_raw = ad5449_read_raw, 199 + .write_raw = ad5449_write_raw, 200 + .driver_module = THIS_MODULE, 201 + }; 202 + 203 + #define AD5449_CHANNEL(chan, bits) { \ 204 + .type = IIO_VOLTAGE, \ 205 + .indexed = 1, \ 206 + .output = 1, \ 207 + .channel = (chan), \ 208 + .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \ 209 + IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \ 210 + .address = (chan), \ 211 + .scan_type = IIO_ST('u', (bits), 16, 12 - (bits)), \ 212 + } 213 + 214 + #define DECLARE_AD5449_CHANNELS(name, bits) \ 215 + const struct iio_chan_spec name[] = { \ 216 + AD5449_CHANNEL(0, bits), \ 217 + AD5449_CHANNEL(1, bits), \ 218 + } 219 + 220 + static DECLARE_AD5449_CHANNELS(ad5429_channels, 8); 221 + static DECLARE_AD5449_CHANNELS(ad5439_channels, 10); 222 + static DECLARE_AD5449_CHANNELS(ad5449_channels, 12); 223 + 224 + static const struct ad5449_chip_info ad5449_chip_info[] = { 225 + [ID_AD5426] = { 226 + .channels = ad5429_channels, 227 + .num_channels = 1, 228 + .has_ctrl = false, 229 + }, 230 + [ID_AD5429] = { 231 + .channels = ad5429_channels, 232 + .num_channels = 2, 233 + .has_ctrl = true, 234 + }, 235 + [ID_AD5432] = { 236 + .channels = ad5439_channels, 237 + .num_channels = 1, 238 + .has_ctrl = false, 239 + }, 240 + [ID_AD5439] = { 241 + .channels = ad5439_channels, 242 + .num_channels = 2, 243 + .has_ctrl = true, 244 + }, 245 + [ID_AD5443] = { 246 + .channels = ad5449_channels, 247 + .num_channels = 1, 248 + .has_ctrl = false, 249 + }, 250 + [ID_AD5449] = { 251 + .channels = ad5449_channels, 252 + .num_channels = 2, 253 + .has_ctrl = true, 254 + }, 255 + }; 256 + 257 + static const char *ad5449_vref_name(struct ad5449 *st, int n) 258 + { 259 + if (st->chip_info->num_channels == 1) 260 + return "VREF"; 261 + 262 + if (n == 0) 263 + return "VREFA"; 264 + else 265 + return "VREFB"; 266 + } 267 + 268 + static int __devinit ad5449_spi_probe(struct spi_device *spi) 269 + { 270 + struct ad5449_platform_data *pdata = spi->dev.platform_data; 271 + const struct spi_device_id *id = spi_get_device_id(spi); 272 + struct iio_dev *indio_dev; 273 + struct ad5449 *st; 274 + unsigned int i; 275 + int ret; 276 + 277 + indio_dev = iio_device_alloc(sizeof(*st)); 278 + if (indio_dev == NULL) 279 + return -ENOMEM; 280 + 281 + st = iio_priv(indio_dev); 282 + spi_set_drvdata(spi, indio_dev); 283 + 284 + st->chip_info = &ad5449_chip_info[id->driver_data]; 285 + st->spi = spi; 286 + 287 + for (i = 0; i < st->chip_info->num_channels; ++i) 288 + st->vref_reg[i].supply = ad5449_vref_name(st, i); 289 + 290 + ret = regulator_bulk_get(&spi->dev, st->chip_info->num_channels, 291 + st->vref_reg); 292 + if (ret) 293 + goto error_free; 294 + 295 + ret = regulator_bulk_enable(st->chip_info->num_channels, st->vref_reg); 296 + if (ret) 297 + goto error_free_reg; 298 + 299 + indio_dev->dev.parent = &spi->dev; 300 + indio_dev->name = id->name; 301 + indio_dev->info = &ad5449_info; 302 + indio_dev->modes = INDIO_DIRECT_MODE; 303 + indio_dev->channels = st->chip_info->channels; 304 + indio_dev->num_channels = st->chip_info->num_channels; 305 + 306 + if (st->chip_info->has_ctrl) { 307 + unsigned int ctrl = 0x00; 308 + if (pdata) { 309 + if (pdata->hardware_clear_to_midscale) 310 + ctrl |= AD5449_CTRL_HCLR_TO_MIDSCALE; 311 + ctrl |= pdata->sdo_mode << AD5449_CTRL_SDO_OFFSET; 312 + st->has_sdo = pdata->sdo_mode != AD5449_SDO_DISABLED; 313 + } else { 314 + st->has_sdo = true; 315 + } 316 + ad5449_write(indio_dev, AD5449_CMD_CTRL, ctrl); 317 + } 318 + 319 + ret = iio_device_register(indio_dev); 320 + if (ret) 321 + goto error_disable_reg; 322 + 323 + return 0; 324 + 325 + error_disable_reg: 326 + regulator_bulk_disable(st->chip_info->num_channels, st->vref_reg); 327 + error_free_reg: 328 + regulator_bulk_free(st->chip_info->num_channels, st->vref_reg); 329 + error_free: 330 + iio_device_free(indio_dev); 331 + 332 + return ret; 333 + } 334 + 335 + static int __devexit ad5449_spi_remove(struct spi_device *spi) 336 + { 337 + struct iio_dev *indio_dev = spi_get_drvdata(spi); 338 + struct ad5449 *st = iio_priv(indio_dev); 339 + 340 + iio_device_unregister(indio_dev); 341 + 342 + regulator_bulk_disable(st->chip_info->num_channels, st->vref_reg); 343 + regulator_bulk_free(st->chip_info->num_channels, st->vref_reg); 344 + 345 + iio_device_free(indio_dev); 346 + 347 + return 0; 348 + } 349 + 350 + static const struct spi_device_id ad5449_spi_ids[] = { 351 + { "ad5415", ID_AD5449 }, 352 + { "ad5426", ID_AD5426 }, 353 + { "ad5429", ID_AD5429 }, 354 + { "ad5432", ID_AD5432 }, 355 + { "ad5439", ID_AD5439 }, 356 + { "ad5443", ID_AD5443 }, 357 + { "ad5449", ID_AD5449 }, 358 + {} 359 + }; 360 + MODULE_DEVICE_TABLE(spi, ad5449_spi_ids); 361 + 362 + static struct spi_driver ad5449_spi_driver = { 363 + .driver = { 364 + .name = "ad5449", 365 + .owner = THIS_MODULE, 366 + }, 367 + .probe = ad5449_spi_probe, 368 + .remove = __devexit_p(ad5449_spi_remove), 369 + .id_table = ad5449_spi_ids, 370 + }; 371 + module_spi_driver(ad5449_spi_driver); 372 + 373 + MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); 374 + MODULE_DESCRIPTION("Analog Devices AD5449 and similar DACs"); 375 + MODULE_LICENSE("GPL v2");
+40
include/linux/platform_data/ad5449.h
··· 1 + /* 2 + * AD5415, AD5426, AD5429, AD5432, AD5439, AD5443, AD5449 Digital to Analog 3 + * Converter driver. 4 + * 5 + * Copyright 2012 Analog Devices Inc. 6 + * Author: Lars-Peter Clausen <lars@metafoo.de> 7 + * 8 + * Licensed under the GPL-2. 9 + */ 10 + 11 + #ifndef __LINUX_PLATFORM_DATA_AD5449_H__ 12 + #define __LINUX_PLATFORM_DATA_AD5449_H__ 13 + 14 + /** 15 + * enum ad5449_sdo_mode - AD5449 SDO pin configuration 16 + * @AD5449_SDO_DRIVE_FULL: Drive the SDO pin with full strength. 17 + * @AD5449_SDO_DRIVE_WEAK: Drive the SDO pin with not full strength. 18 + * @AD5449_SDO_OPEN_DRAIN: Operate the SDO pin in open-drain mode. 19 + * @AD5449_SDO_DISABLED: Disable the SDO pin, in this mode it is not possible to 20 + * read back from the device. 21 + */ 22 + enum ad5449_sdo_mode { 23 + AD5449_SDO_DRIVE_FULL = 0x0, 24 + AD5449_SDO_DRIVE_WEAK = 0x1, 25 + AD5449_SDO_OPEN_DRAIN = 0x2, 26 + AD5449_SDO_DISABLED = 0x3, 27 + }; 28 + 29 + /** 30 + * struct ad5449_platform_data - Platform data for the ad5449 DAC driver 31 + * @sdo_mode: SDO pin mode 32 + * @hardware_clear_to_midscale: Whether asserting the hardware CLR pin sets the 33 + * outputs to midscale (true) or to zero scale(false). 34 + */ 35 + struct ad5449_platform_data { 36 + enum ad5449_sdo_mode sdo_mode; 37 + bool hardware_clear_to_midscale; 38 + }; 39 + 40 + #endif