ad5504.c (8682B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * AD5504, AD5501 High Voltage Digital to Analog Converter 4 * 5 * Copyright 2011 Analog Devices Inc. 6 */ 7 8#include <linux/interrupt.h> 9#include <linux/fs.h> 10#include <linux/device.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/module.h> 17#include <linux/bitops.h> 18 19#include <linux/iio/iio.h> 20#include <linux/iio/sysfs.h> 21#include <linux/iio/events.h> 22#include <linux/iio/dac/ad5504.h> 23 24#define AD5504_RES_MASK GENMASK(11, 0) 25#define AD5504_CMD_READ BIT(15) 26#define AD5504_CMD_WRITE 0 27#define AD5504_ADDR(addr) ((addr) << 12) 28 29/* Registers */ 30#define AD5504_ADDR_NOOP 0 31#define AD5504_ADDR_DAC(x) ((x) + 1) 32#define AD5504_ADDR_ALL_DAC 5 33#define AD5504_ADDR_CTRL 7 34 35/* Control Register */ 36#define AD5504_DAC_PWR(ch) ((ch) << 2) 37#define AD5504_DAC_PWRDWN_MODE(mode) ((mode) << 6) 38#define AD5504_DAC_PWRDN_20K 0 39#define AD5504_DAC_PWRDN_3STATE 1 40 41/** 42 * struct ad5504_state - driver instance specific data 43 * @spi: spi_device 44 * @reg: supply regulator 45 * @vref_mv: actual reference voltage used 46 * @pwr_down_mask: power down mask 47 * @pwr_down_mode: current power down mode 48 * @data: transfer buffer 49 */ 50struct ad5504_state { 51 struct spi_device *spi; 52 struct regulator *reg; 53 unsigned short vref_mv; 54 unsigned pwr_down_mask; 55 unsigned pwr_down_mode; 56 57 __be16 data[2] ____cacheline_aligned; 58}; 59 60/* 61 * ad5504_supported_device_ids: 62 */ 63enum ad5504_supported_device_ids { 64 ID_AD5504, 65 ID_AD5501, 66}; 67 68static int ad5504_spi_write(struct ad5504_state *st, u8 addr, u16 val) 69{ 70 st->data[0] = cpu_to_be16(AD5504_CMD_WRITE | AD5504_ADDR(addr) | 71 (val & AD5504_RES_MASK)); 72 73 return spi_write(st->spi, &st->data[0], 2); 74} 75 76static int ad5504_spi_read(struct ad5504_state *st, u8 addr) 77{ 78 int ret; 79 struct spi_transfer t = { 80 .tx_buf = &st->data[0], 81 .rx_buf = &st->data[1], 82 .len = 2, 83 }; 84 85 st->data[0] = cpu_to_be16(AD5504_CMD_READ | AD5504_ADDR(addr)); 86 ret = spi_sync_transfer(st->spi, &t, 1); 87 if (ret < 0) 88 return ret; 89 90 return be16_to_cpu(st->data[1]) & AD5504_RES_MASK; 91} 92 93static int ad5504_read_raw(struct iio_dev *indio_dev, 94 struct iio_chan_spec const *chan, 95 int *val, 96 int *val2, 97 long m) 98{ 99 struct ad5504_state *st = iio_priv(indio_dev); 100 int ret; 101 102 switch (m) { 103 case IIO_CHAN_INFO_RAW: 104 ret = ad5504_spi_read(st, chan->address); 105 if (ret < 0) 106 return ret; 107 108 *val = ret; 109 110 return IIO_VAL_INT; 111 case IIO_CHAN_INFO_SCALE: 112 *val = st->vref_mv; 113 *val2 = chan->scan_type.realbits; 114 return IIO_VAL_FRACTIONAL_LOG2; 115 } 116 return -EINVAL; 117} 118 119static int ad5504_write_raw(struct iio_dev *indio_dev, 120 struct iio_chan_spec const *chan, 121 int val, 122 int val2, 123 long mask) 124{ 125 struct ad5504_state *st = iio_priv(indio_dev); 126 127 switch (mask) { 128 case IIO_CHAN_INFO_RAW: 129 if (val >= (1 << chan->scan_type.realbits) || val < 0) 130 return -EINVAL; 131 132 return ad5504_spi_write(st, chan->address, val); 133 default: 134 return -EINVAL; 135 } 136} 137 138static const char * const ad5504_powerdown_modes[] = { 139 "20kohm_to_gnd", 140 "three_state", 141}; 142 143static int ad5504_get_powerdown_mode(struct iio_dev *indio_dev, 144 const struct iio_chan_spec *chan) 145{ 146 struct ad5504_state *st = iio_priv(indio_dev); 147 148 return st->pwr_down_mode; 149} 150 151static int ad5504_set_powerdown_mode(struct iio_dev *indio_dev, 152 const struct iio_chan_spec *chan, unsigned int mode) 153{ 154 struct ad5504_state *st = iio_priv(indio_dev); 155 156 st->pwr_down_mode = mode; 157 158 return 0; 159} 160 161static const struct iio_enum ad5504_powerdown_mode_enum = { 162 .items = ad5504_powerdown_modes, 163 .num_items = ARRAY_SIZE(ad5504_powerdown_modes), 164 .get = ad5504_get_powerdown_mode, 165 .set = ad5504_set_powerdown_mode, 166}; 167 168static ssize_t ad5504_read_dac_powerdown(struct iio_dev *indio_dev, 169 uintptr_t private, const struct iio_chan_spec *chan, char *buf) 170{ 171 struct ad5504_state *st = iio_priv(indio_dev); 172 173 return sysfs_emit(buf, "%d\n", 174 !(st->pwr_down_mask & (1 << chan->channel))); 175} 176 177static ssize_t ad5504_write_dac_powerdown(struct iio_dev *indio_dev, 178 uintptr_t private, const struct iio_chan_spec *chan, const char *buf, 179 size_t len) 180{ 181 bool pwr_down; 182 int ret; 183 struct ad5504_state *st = iio_priv(indio_dev); 184 185 ret = kstrtobool(buf, &pwr_down); 186 if (ret) 187 return ret; 188 189 if (pwr_down) 190 st->pwr_down_mask &= ~(1 << chan->channel); 191 else 192 st->pwr_down_mask |= (1 << chan->channel); 193 194 ret = ad5504_spi_write(st, AD5504_ADDR_CTRL, 195 AD5504_DAC_PWRDWN_MODE(st->pwr_down_mode) | 196 AD5504_DAC_PWR(st->pwr_down_mask)); 197 198 /* writes to the CTRL register must be followed by a NOOP */ 199 ad5504_spi_write(st, AD5504_ADDR_NOOP, 0); 200 201 return ret ? ret : len; 202} 203 204static IIO_CONST_ATTR(temp0_thresh_rising_value, "110000"); 205static IIO_CONST_ATTR(temp0_thresh_rising_en, "1"); 206 207static struct attribute *ad5504_ev_attributes[] = { 208 &iio_const_attr_temp0_thresh_rising_value.dev_attr.attr, 209 &iio_const_attr_temp0_thresh_rising_en.dev_attr.attr, 210 NULL, 211}; 212 213static const struct attribute_group ad5504_ev_attribute_group = { 214 .attrs = ad5504_ev_attributes, 215}; 216 217static irqreturn_t ad5504_event_handler(int irq, void *private) 218{ 219 iio_push_event(private, 220 IIO_UNMOD_EVENT_CODE(IIO_TEMP, 221 0, 222 IIO_EV_TYPE_THRESH, 223 IIO_EV_DIR_RISING), 224 iio_get_time_ns(private)); 225 226 return IRQ_HANDLED; 227} 228 229static const struct iio_info ad5504_info = { 230 .write_raw = ad5504_write_raw, 231 .read_raw = ad5504_read_raw, 232 .event_attrs = &ad5504_ev_attribute_group, 233}; 234 235static const struct iio_chan_spec_ext_info ad5504_ext_info[] = { 236 { 237 .name = "powerdown", 238 .read = ad5504_read_dac_powerdown, 239 .write = ad5504_write_dac_powerdown, 240 .shared = IIO_SEPARATE, 241 }, 242 IIO_ENUM("powerdown_mode", IIO_SHARED_BY_TYPE, 243 &ad5504_powerdown_mode_enum), 244 IIO_ENUM_AVAILABLE("powerdown_mode", IIO_SHARED_BY_TYPE, &ad5504_powerdown_mode_enum), 245 { }, 246}; 247 248#define AD5504_CHANNEL(_chan) { \ 249 .type = IIO_VOLTAGE, \ 250 .indexed = 1, \ 251 .output = 1, \ 252 .channel = (_chan), \ 253 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ 254 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ 255 .address = AD5504_ADDR_DAC(_chan), \ 256 .scan_type = { \ 257 .sign = 'u', \ 258 .realbits = 12, \ 259 .storagebits = 16, \ 260 }, \ 261 .ext_info = ad5504_ext_info, \ 262} 263 264static const struct iio_chan_spec ad5504_channels[] = { 265 AD5504_CHANNEL(0), 266 AD5504_CHANNEL(1), 267 AD5504_CHANNEL(2), 268 AD5504_CHANNEL(3), 269}; 270 271static int ad5504_probe(struct spi_device *spi) 272{ 273 struct ad5504_platform_data *pdata = spi->dev.platform_data; 274 struct iio_dev *indio_dev; 275 struct ad5504_state *st; 276 struct regulator *reg; 277 int ret, voltage_uv = 0; 278 279 indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); 280 if (!indio_dev) 281 return -ENOMEM; 282 reg = devm_regulator_get(&spi->dev, "vcc"); 283 if (!IS_ERR(reg)) { 284 ret = regulator_enable(reg); 285 if (ret) 286 return ret; 287 288 ret = regulator_get_voltage(reg); 289 if (ret < 0) 290 goto error_disable_reg; 291 292 voltage_uv = ret; 293 } 294 295 spi_set_drvdata(spi, indio_dev); 296 st = iio_priv(indio_dev); 297 if (voltage_uv) 298 st->vref_mv = voltage_uv / 1000; 299 else if (pdata) 300 st->vref_mv = pdata->vref_mv; 301 else 302 dev_warn(&spi->dev, "reference voltage unspecified\n"); 303 304 st->reg = reg; 305 st->spi = spi; 306 indio_dev->name = spi_get_device_id(st->spi)->name; 307 indio_dev->info = &ad5504_info; 308 if (spi_get_device_id(st->spi)->driver_data == ID_AD5501) 309 indio_dev->num_channels = 1; 310 else 311 indio_dev->num_channels = 4; 312 indio_dev->channels = ad5504_channels; 313 indio_dev->modes = INDIO_DIRECT_MODE; 314 315 if (spi->irq) { 316 ret = devm_request_threaded_irq(&spi->dev, spi->irq, 317 NULL, 318 &ad5504_event_handler, 319 IRQF_TRIGGER_FALLING | IRQF_ONESHOT, 320 spi_get_device_id(st->spi)->name, 321 indio_dev); 322 if (ret) 323 goto error_disable_reg; 324 } 325 326 ret = iio_device_register(indio_dev); 327 if (ret) 328 goto error_disable_reg; 329 330 return 0; 331 332error_disable_reg: 333 if (!IS_ERR(reg)) 334 regulator_disable(reg); 335 336 return ret; 337} 338 339static void ad5504_remove(struct spi_device *spi) 340{ 341 struct iio_dev *indio_dev = spi_get_drvdata(spi); 342 struct ad5504_state *st = iio_priv(indio_dev); 343 344 iio_device_unregister(indio_dev); 345 346 if (!IS_ERR(st->reg)) 347 regulator_disable(st->reg); 348} 349 350static const struct spi_device_id ad5504_id[] = { 351 {"ad5504", ID_AD5504}, 352 {"ad5501", ID_AD5501}, 353 {} 354}; 355MODULE_DEVICE_TABLE(spi, ad5504_id); 356 357static struct spi_driver ad5504_driver = { 358 .driver = { 359 .name = "ad5504", 360 }, 361 .probe = ad5504_probe, 362 .remove = ad5504_remove, 363 .id_table = ad5504_id, 364}; 365module_spi_driver(ad5504_driver); 366 367MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>"); 368MODULE_DESCRIPTION("Analog Devices AD5501/AD5501 DAC"); 369MODULE_LICENSE("GPL v2");