ad5791.c (11328B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * AD5760, AD5780, AD5781, AD5790, AD5791 Voltage Output Digital to Analog 4 * Converter 5 * 6 * Copyright 2011 Analog Devices Inc. 7 */ 8 9#include <linux/interrupt.h> 10#include <linux/fs.h> 11#include <linux/device.h> 12#include <linux/kernel.h> 13#include <linux/spi/spi.h> 14#include <linux/slab.h> 15#include <linux/sysfs.h> 16#include <linux/regulator/consumer.h> 17#include <linux/module.h> 18#include <linux/bitops.h> 19 20#include <linux/iio/iio.h> 21#include <linux/iio/sysfs.h> 22#include <linux/iio/dac/ad5791.h> 23 24#define AD5791_DAC_MASK GENMASK(19, 0) 25 26#define AD5791_CMD_READ BIT(23) 27#define AD5791_CMD_WRITE 0 28#define AD5791_ADDR(addr) ((addr) << 20) 29 30/* Registers */ 31#define AD5791_ADDR_NOOP 0 32#define AD5791_ADDR_DAC0 1 33#define AD5791_ADDR_CTRL 2 34#define AD5791_ADDR_CLRCODE 3 35#define AD5791_ADDR_SW_CTRL 4 36 37/* Control Register */ 38#define AD5791_CTRL_RBUF BIT(1) 39#define AD5791_CTRL_OPGND BIT(2) 40#define AD5791_CTRL_DACTRI BIT(3) 41#define AD5791_CTRL_BIN2SC BIT(4) 42#define AD5791_CTRL_SDODIS BIT(5) 43#define AD5761_CTRL_LINCOMP(x) ((x) << 6) 44 45#define AD5791_LINCOMP_0_10 0 46#define AD5791_LINCOMP_10_12 1 47#define AD5791_LINCOMP_12_16 2 48#define AD5791_LINCOMP_16_19 3 49#define AD5791_LINCOMP_19_20 12 50 51#define AD5780_LINCOMP_0_10 0 52#define AD5780_LINCOMP_10_20 12 53 54/* Software Control Register */ 55#define AD5791_SWCTRL_LDAC BIT(0) 56#define AD5791_SWCTRL_CLR BIT(1) 57#define AD5791_SWCTRL_RESET BIT(2) 58 59#define AD5791_DAC_PWRDN_6K 0 60#define AD5791_DAC_PWRDN_3STATE 1 61 62/** 63 * struct ad5791_chip_info - chip specific information 64 * @get_lin_comp: function pointer to the device specific function 65 */ 66 67struct ad5791_chip_info { 68 int (*get_lin_comp) (unsigned int span); 69}; 70 71/** 72 * struct ad5791_state - driver instance specific data 73 * @spi: spi_device 74 * @reg_vdd: positive supply regulator 75 * @reg_vss: negative supply regulator 76 * @chip_info: chip model specific constants 77 * @vref_mv: actual reference voltage used 78 * @vref_neg_mv: voltage of the negative supply 79 * @ctrl: control register cache 80 * @pwr_down_mode: current power down mode 81 * @pwr_down: true if device is powered down 82 * @data: spi transfer buffers 83 */ 84struct ad5791_state { 85 struct spi_device *spi; 86 struct regulator *reg_vdd; 87 struct regulator *reg_vss; 88 const struct ad5791_chip_info *chip_info; 89 unsigned short vref_mv; 90 unsigned int vref_neg_mv; 91 unsigned ctrl; 92 unsigned pwr_down_mode; 93 bool pwr_down; 94 95 union { 96 __be32 d32; 97 u8 d8[4]; 98 } data[3] ____cacheline_aligned; 99}; 100 101enum ad5791_supported_device_ids { 102 ID_AD5760, 103 ID_AD5780, 104 ID_AD5781, 105 ID_AD5791, 106}; 107 108static int ad5791_spi_write(struct ad5791_state *st, u8 addr, u32 val) 109{ 110 st->data[0].d32 = cpu_to_be32(AD5791_CMD_WRITE | 111 AD5791_ADDR(addr) | 112 (val & AD5791_DAC_MASK)); 113 114 return spi_write(st->spi, &st->data[0].d8[1], 3); 115} 116 117static int ad5791_spi_read(struct ad5791_state *st, u8 addr, u32 *val) 118{ 119 int ret; 120 struct spi_transfer xfers[] = { 121 { 122 .tx_buf = &st->data[0].d8[1], 123 .bits_per_word = 8, 124 .len = 3, 125 .cs_change = 1, 126 }, { 127 .tx_buf = &st->data[1].d8[1], 128 .rx_buf = &st->data[2].d8[1], 129 .bits_per_word = 8, 130 .len = 3, 131 }, 132 }; 133 134 st->data[0].d32 = cpu_to_be32(AD5791_CMD_READ | 135 AD5791_ADDR(addr)); 136 st->data[1].d32 = cpu_to_be32(AD5791_ADDR(AD5791_ADDR_NOOP)); 137 138 ret = spi_sync_transfer(st->spi, xfers, ARRAY_SIZE(xfers)); 139 140 *val = be32_to_cpu(st->data[2].d32); 141 142 return ret; 143} 144 145static const char * const ad5791_powerdown_modes[] = { 146 "6kohm_to_gnd", 147 "three_state", 148}; 149 150static int ad5791_get_powerdown_mode(struct iio_dev *indio_dev, 151 const struct iio_chan_spec *chan) 152{ 153 struct ad5791_state *st = iio_priv(indio_dev); 154 155 return st->pwr_down_mode; 156} 157 158static int ad5791_set_powerdown_mode(struct iio_dev *indio_dev, 159 const struct iio_chan_spec *chan, unsigned int mode) 160{ 161 struct ad5791_state *st = iio_priv(indio_dev); 162 163 st->pwr_down_mode = mode; 164 165 return 0; 166} 167 168static const struct iio_enum ad5791_powerdown_mode_enum = { 169 .items = ad5791_powerdown_modes, 170 .num_items = ARRAY_SIZE(ad5791_powerdown_modes), 171 .get = ad5791_get_powerdown_mode, 172 .set = ad5791_set_powerdown_mode, 173}; 174 175static ssize_t ad5791_read_dac_powerdown(struct iio_dev *indio_dev, 176 uintptr_t private, const struct iio_chan_spec *chan, char *buf) 177{ 178 struct ad5791_state *st = iio_priv(indio_dev); 179 180 return sysfs_emit(buf, "%d\n", st->pwr_down); 181} 182 183static ssize_t ad5791_write_dac_powerdown(struct iio_dev *indio_dev, 184 uintptr_t private, const struct iio_chan_spec *chan, const char *buf, 185 size_t len) 186{ 187 bool pwr_down; 188 int ret; 189 struct ad5791_state *st = iio_priv(indio_dev); 190 191 ret = kstrtobool(buf, &pwr_down); 192 if (ret) 193 return ret; 194 195 if (!pwr_down) { 196 st->ctrl &= ~(AD5791_CTRL_OPGND | AD5791_CTRL_DACTRI); 197 } else { 198 if (st->pwr_down_mode == AD5791_DAC_PWRDN_6K) 199 st->ctrl |= AD5791_CTRL_OPGND; 200 else if (st->pwr_down_mode == AD5791_DAC_PWRDN_3STATE) 201 st->ctrl |= AD5791_CTRL_DACTRI; 202 } 203 st->pwr_down = pwr_down; 204 205 ret = ad5791_spi_write(st, AD5791_ADDR_CTRL, st->ctrl); 206 207 return ret ? ret : len; 208} 209 210static int ad5791_get_lin_comp(unsigned int span) 211{ 212 if (span <= 10000) 213 return AD5791_LINCOMP_0_10; 214 else if (span <= 12000) 215 return AD5791_LINCOMP_10_12; 216 else if (span <= 16000) 217 return AD5791_LINCOMP_12_16; 218 else if (span <= 19000) 219 return AD5791_LINCOMP_16_19; 220 else 221 return AD5791_LINCOMP_19_20; 222} 223 224static int ad5780_get_lin_comp(unsigned int span) 225{ 226 if (span <= 10000) 227 return AD5780_LINCOMP_0_10; 228 else 229 return AD5780_LINCOMP_10_20; 230} 231static const struct ad5791_chip_info ad5791_chip_info_tbl[] = { 232 [ID_AD5760] = { 233 .get_lin_comp = ad5780_get_lin_comp, 234 }, 235 [ID_AD5780] = { 236 .get_lin_comp = ad5780_get_lin_comp, 237 }, 238 [ID_AD5781] = { 239 .get_lin_comp = ad5791_get_lin_comp, 240 }, 241 [ID_AD5791] = { 242 .get_lin_comp = ad5791_get_lin_comp, 243 }, 244}; 245 246static int ad5791_read_raw(struct iio_dev *indio_dev, 247 struct iio_chan_spec const *chan, 248 int *val, 249 int *val2, 250 long m) 251{ 252 struct ad5791_state *st = iio_priv(indio_dev); 253 u64 val64; 254 int ret; 255 256 switch (m) { 257 case IIO_CHAN_INFO_RAW: 258 ret = ad5791_spi_read(st, chan->address, val); 259 if (ret) 260 return ret; 261 *val &= AD5791_DAC_MASK; 262 *val >>= chan->scan_type.shift; 263 return IIO_VAL_INT; 264 case IIO_CHAN_INFO_SCALE: 265 *val = st->vref_mv; 266 *val2 = (1 << chan->scan_type.realbits) - 1; 267 return IIO_VAL_FRACTIONAL; 268 case IIO_CHAN_INFO_OFFSET: 269 val64 = (((u64)st->vref_neg_mv) << chan->scan_type.realbits); 270 do_div(val64, st->vref_mv); 271 *val = -val64; 272 return IIO_VAL_INT; 273 default: 274 return -EINVAL; 275 } 276 277}; 278 279static const struct iio_chan_spec_ext_info ad5791_ext_info[] = { 280 { 281 .name = "powerdown", 282 .shared = IIO_SHARED_BY_TYPE, 283 .read = ad5791_read_dac_powerdown, 284 .write = ad5791_write_dac_powerdown, 285 }, 286 IIO_ENUM("powerdown_mode", IIO_SHARED_BY_TYPE, 287 &ad5791_powerdown_mode_enum), 288 IIO_ENUM_AVAILABLE("powerdown_mode", IIO_SHARED_BY_TYPE, &ad5791_powerdown_mode_enum), 289 { }, 290}; 291 292#define AD5791_CHAN(bits, _shift) { \ 293 .type = IIO_VOLTAGE, \ 294 .output = 1, \ 295 .indexed = 1, \ 296 .address = AD5791_ADDR_DAC0, \ 297 .channel = 0, \ 298 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ 299 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ 300 BIT(IIO_CHAN_INFO_OFFSET), \ 301 .scan_type = { \ 302 .sign = 'u', \ 303 .realbits = (bits), \ 304 .storagebits = 24, \ 305 .shift = (_shift), \ 306 }, \ 307 .ext_info = ad5791_ext_info, \ 308} 309 310static const struct iio_chan_spec ad5791_channels[] = { 311 [ID_AD5760] = AD5791_CHAN(16, 4), 312 [ID_AD5780] = AD5791_CHAN(18, 2), 313 [ID_AD5781] = AD5791_CHAN(18, 2), 314 [ID_AD5791] = AD5791_CHAN(20, 0) 315}; 316 317static int ad5791_write_raw(struct iio_dev *indio_dev, 318 struct iio_chan_spec const *chan, 319 int val, 320 int val2, 321 long mask) 322{ 323 struct ad5791_state *st = iio_priv(indio_dev); 324 325 switch (mask) { 326 case IIO_CHAN_INFO_RAW: 327 val &= GENMASK(chan->scan_type.realbits - 1, 0); 328 val <<= chan->scan_type.shift; 329 330 return ad5791_spi_write(st, chan->address, val); 331 332 default: 333 return -EINVAL; 334 } 335} 336 337static const struct iio_info ad5791_info = { 338 .read_raw = &ad5791_read_raw, 339 .write_raw = &ad5791_write_raw, 340}; 341 342static int ad5791_probe(struct spi_device *spi) 343{ 344 struct ad5791_platform_data *pdata = spi->dev.platform_data; 345 struct iio_dev *indio_dev; 346 struct ad5791_state *st; 347 int ret, pos_voltage_uv = 0, neg_voltage_uv = 0; 348 349 indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); 350 if (!indio_dev) 351 return -ENOMEM; 352 st = iio_priv(indio_dev); 353 st->reg_vdd = devm_regulator_get(&spi->dev, "vdd"); 354 if (!IS_ERR(st->reg_vdd)) { 355 ret = regulator_enable(st->reg_vdd); 356 if (ret) 357 return ret; 358 359 ret = regulator_get_voltage(st->reg_vdd); 360 if (ret < 0) 361 goto error_disable_reg_pos; 362 363 pos_voltage_uv = ret; 364 } 365 366 st->reg_vss = devm_regulator_get(&spi->dev, "vss"); 367 if (!IS_ERR(st->reg_vss)) { 368 ret = regulator_enable(st->reg_vss); 369 if (ret) 370 goto error_disable_reg_pos; 371 372 ret = regulator_get_voltage(st->reg_vss); 373 if (ret < 0) 374 goto error_disable_reg_neg; 375 376 neg_voltage_uv = ret; 377 } 378 379 st->pwr_down = true; 380 st->spi = spi; 381 382 if (!IS_ERR(st->reg_vss) && !IS_ERR(st->reg_vdd)) { 383 st->vref_mv = (pos_voltage_uv + neg_voltage_uv) / 1000; 384 st->vref_neg_mv = neg_voltage_uv / 1000; 385 } else if (pdata) { 386 st->vref_mv = pdata->vref_pos_mv + pdata->vref_neg_mv; 387 st->vref_neg_mv = pdata->vref_neg_mv; 388 } else { 389 dev_warn(&spi->dev, "reference voltage unspecified\n"); 390 } 391 392 ret = ad5791_spi_write(st, AD5791_ADDR_SW_CTRL, AD5791_SWCTRL_RESET); 393 if (ret) 394 goto error_disable_reg_neg; 395 396 st->chip_info = &ad5791_chip_info_tbl[spi_get_device_id(spi) 397 ->driver_data]; 398 399 400 st->ctrl = AD5761_CTRL_LINCOMP(st->chip_info->get_lin_comp(st->vref_mv)) 401 | ((pdata && pdata->use_rbuf_gain2) ? 0 : AD5791_CTRL_RBUF) | 402 AD5791_CTRL_BIN2SC; 403 404 ret = ad5791_spi_write(st, AD5791_ADDR_CTRL, st->ctrl | 405 AD5791_CTRL_OPGND | AD5791_CTRL_DACTRI); 406 if (ret) 407 goto error_disable_reg_neg; 408 409 spi_set_drvdata(spi, indio_dev); 410 indio_dev->info = &ad5791_info; 411 indio_dev->modes = INDIO_DIRECT_MODE; 412 indio_dev->channels 413 = &ad5791_channels[spi_get_device_id(spi)->driver_data]; 414 indio_dev->num_channels = 1; 415 indio_dev->name = spi_get_device_id(st->spi)->name; 416 ret = iio_device_register(indio_dev); 417 if (ret) 418 goto error_disable_reg_neg; 419 420 return 0; 421 422error_disable_reg_neg: 423 if (!IS_ERR(st->reg_vss)) 424 regulator_disable(st->reg_vss); 425error_disable_reg_pos: 426 if (!IS_ERR(st->reg_vdd)) 427 regulator_disable(st->reg_vdd); 428 return ret; 429} 430 431static void ad5791_remove(struct spi_device *spi) 432{ 433 struct iio_dev *indio_dev = spi_get_drvdata(spi); 434 struct ad5791_state *st = iio_priv(indio_dev); 435 436 iio_device_unregister(indio_dev); 437 if (!IS_ERR(st->reg_vdd)) 438 regulator_disable(st->reg_vdd); 439 440 if (!IS_ERR(st->reg_vss)) 441 regulator_disable(st->reg_vss); 442} 443 444static const struct spi_device_id ad5791_id[] = { 445 {"ad5760", ID_AD5760}, 446 {"ad5780", ID_AD5780}, 447 {"ad5781", ID_AD5781}, 448 {"ad5790", ID_AD5791}, 449 {"ad5791", ID_AD5791}, 450 {} 451}; 452MODULE_DEVICE_TABLE(spi, ad5791_id); 453 454static struct spi_driver ad5791_driver = { 455 .driver = { 456 .name = "ad5791", 457 }, 458 .probe = ad5791_probe, 459 .remove = ad5791_remove, 460 .id_table = ad5791_id, 461}; 462module_spi_driver(ad5791_driver); 463 464MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>"); 465MODULE_DESCRIPTION("Analog Devices AD5760/AD5780/AD5781/AD5790/AD5791 DAC"); 466MODULE_LICENSE("GPL v2");