1fda8d26eSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 2dbdc025bSLars-Peter Clausen /* 3dbdc025bSLars-Peter Clausen * AD5421 Digital to analog converters driver 4dbdc025bSLars-Peter Clausen * 5dbdc025bSLars-Peter Clausen * Copyright 2011 Analog Devices Inc. 6dbdc025bSLars-Peter Clausen */ 7dbdc025bSLars-Peter Clausen 8dbdc025bSLars-Peter Clausen #include <linux/device.h> 9dbdc025bSLars-Peter Clausen #include <linux/delay.h> 10dbdc025bSLars-Peter Clausen #include <linux/err.h> 11dbdc025bSLars-Peter Clausen #include <linux/module.h> 12dbdc025bSLars-Peter Clausen #include <linux/interrupt.h> 13dbdc025bSLars-Peter Clausen #include <linux/kernel.h> 14dbdc025bSLars-Peter Clausen #include <linux/spi/spi.h> 15dbdc025bSLars-Peter Clausen #include <linux/slab.h> 16dbdc025bSLars-Peter Clausen #include <linux/sysfs.h> 17dbdc025bSLars-Peter Clausen 18dbdc025bSLars-Peter Clausen #include <linux/iio/iio.h> 19dbdc025bSLars-Peter Clausen #include <linux/iio/sysfs.h> 20dbdc025bSLars-Peter Clausen #include <linux/iio/events.h> 21dbdc025bSLars-Peter Clausen #include <linux/iio/dac/ad5421.h> 22dbdc025bSLars-Peter Clausen 23dbdc025bSLars-Peter Clausen 24dbdc025bSLars-Peter Clausen #define AD5421_REG_DAC_DATA 0x1 25dbdc025bSLars-Peter Clausen #define AD5421_REG_CTRL 0x2 26dbdc025bSLars-Peter Clausen #define AD5421_REG_OFFSET 0x3 27dbdc025bSLars-Peter Clausen #define AD5421_REG_GAIN 0x4 28dbdc025bSLars-Peter Clausen /* load dac and fault shared the same register number. Writing to it will cause 29dbdc025bSLars-Peter Clausen * a dac load command, reading from it will return the fault status register */ 30dbdc025bSLars-Peter Clausen #define AD5421_REG_LOAD_DAC 0x5 31dbdc025bSLars-Peter Clausen #define AD5421_REG_FAULT 0x5 32dbdc025bSLars-Peter Clausen #define AD5421_REG_FORCE_ALARM_CURRENT 0x6 33dbdc025bSLars-Peter Clausen #define AD5421_REG_RESET 0x7 34dbdc025bSLars-Peter Clausen #define AD5421_REG_START_CONVERSION 0x8 35dbdc025bSLars-Peter Clausen #define AD5421_REG_NOOP 0x9 36dbdc025bSLars-Peter Clausen 37dbdc025bSLars-Peter Clausen #define AD5421_CTRL_WATCHDOG_DISABLE BIT(12) 38dbdc025bSLars-Peter Clausen #define AD5421_CTRL_AUTO_FAULT_READBACK BIT(11) 39dbdc025bSLars-Peter Clausen #define AD5421_CTRL_MIN_CURRENT BIT(9) 40dbdc025bSLars-Peter Clausen #define AD5421_CTRL_ADC_SOURCE_TEMP BIT(8) 41dbdc025bSLars-Peter Clausen #define AD5421_CTRL_ADC_ENABLE BIT(7) 42dbdc025bSLars-Peter Clausen #define AD5421_CTRL_PWR_DOWN_INT_VREF BIT(6) 43dbdc025bSLars-Peter Clausen 44dbdc025bSLars-Peter Clausen #define AD5421_FAULT_SPI BIT(15) 45dbdc025bSLars-Peter Clausen #define AD5421_FAULT_PEC BIT(14) 46dbdc025bSLars-Peter Clausen #define AD5421_FAULT_OVER_CURRENT BIT(13) 47dbdc025bSLars-Peter Clausen #define AD5421_FAULT_UNDER_CURRENT BIT(12) 48dbdc025bSLars-Peter Clausen #define AD5421_FAULT_TEMP_OVER_140 BIT(11) 49dbdc025bSLars-Peter Clausen #define AD5421_FAULT_TEMP_OVER_100 BIT(10) 50dbdc025bSLars-Peter Clausen #define AD5421_FAULT_UNDER_VOLTAGE_6V BIT(9) 51dbdc025bSLars-Peter Clausen #define AD5421_FAULT_UNDER_VOLTAGE_12V BIT(8) 52dbdc025bSLars-Peter Clausen 53dbdc025bSLars-Peter Clausen /* These bits will cause the fault pin to go high */ 54dbdc025bSLars-Peter Clausen #define AD5421_FAULT_TRIGGER_IRQ \ 55dbdc025bSLars-Peter Clausen (AD5421_FAULT_SPI | AD5421_FAULT_PEC | AD5421_FAULT_OVER_CURRENT | \ 56dbdc025bSLars-Peter Clausen AD5421_FAULT_UNDER_CURRENT | AD5421_FAULT_TEMP_OVER_140) 57dbdc025bSLars-Peter Clausen 58dbdc025bSLars-Peter Clausen /** 59dbdc025bSLars-Peter Clausen * struct ad5421_state - driver instance specific data 60dbdc025bSLars-Peter Clausen * @spi: spi_device 61dbdc025bSLars-Peter Clausen * @ctrl: control register cache 62dbdc025bSLars-Peter Clausen * @current_range: current range which the device is configured for 63dbdc025bSLars-Peter Clausen * @data: spi transfer buffers 64dbdc025bSLars-Peter Clausen * @fault_mask: software masking of events 65dbdc025bSLars-Peter Clausen */ 66dbdc025bSLars-Peter Clausen struct ad5421_state { 67dbdc025bSLars-Peter Clausen struct spi_device *spi; 68dbdc025bSLars-Peter Clausen unsigned int ctrl; 69dbdc025bSLars-Peter Clausen enum ad5421_current_range current_range; 70dbdc025bSLars-Peter Clausen unsigned int fault_mask; 71dbdc025bSLars-Peter Clausen 72dbdc025bSLars-Peter Clausen /* 73dbdc025bSLars-Peter Clausen * DMA (thus cache coherency maintenance) requires the 74dbdc025bSLars-Peter Clausen * transfer buffers to live in their own cache lines. 75dbdc025bSLars-Peter Clausen */ 76dbdc025bSLars-Peter Clausen union { 778ef411b7SLars-Peter Clausen __be32 d32; 78dbdc025bSLars-Peter Clausen u8 d8[4]; 79dbdc025bSLars-Peter Clausen } data[2] ____cacheline_aligned; 80dbdc025bSLars-Peter Clausen }; 81dbdc025bSLars-Peter Clausen 821eefd62bSLars-Peter Clausen static const struct iio_event_spec ad5421_current_event[] = { 831eefd62bSLars-Peter Clausen { 841eefd62bSLars-Peter Clausen .type = IIO_EV_TYPE_THRESH, 851eefd62bSLars-Peter Clausen .dir = IIO_EV_DIR_RISING, 861eefd62bSLars-Peter Clausen .mask_separate = BIT(IIO_EV_INFO_VALUE) | 871eefd62bSLars-Peter Clausen BIT(IIO_EV_INFO_ENABLE), 881eefd62bSLars-Peter Clausen }, { 891eefd62bSLars-Peter Clausen .type = IIO_EV_TYPE_THRESH, 901eefd62bSLars-Peter Clausen .dir = IIO_EV_DIR_FALLING, 911eefd62bSLars-Peter Clausen .mask_separate = BIT(IIO_EV_INFO_VALUE) | 921eefd62bSLars-Peter Clausen BIT(IIO_EV_INFO_ENABLE), 931eefd62bSLars-Peter Clausen }, 941eefd62bSLars-Peter Clausen }; 951eefd62bSLars-Peter Clausen 961eefd62bSLars-Peter Clausen static const struct iio_event_spec ad5421_temp_event[] = { 971eefd62bSLars-Peter Clausen { 981eefd62bSLars-Peter Clausen .type = IIO_EV_TYPE_THRESH, 991eefd62bSLars-Peter Clausen .dir = IIO_EV_DIR_RISING, 1001eefd62bSLars-Peter Clausen .mask_separate = BIT(IIO_EV_INFO_VALUE) | 1011eefd62bSLars-Peter Clausen BIT(IIO_EV_INFO_ENABLE), 1021eefd62bSLars-Peter Clausen }, 1031eefd62bSLars-Peter Clausen }; 1041eefd62bSLars-Peter Clausen 105dbdc025bSLars-Peter Clausen static const struct iio_chan_spec ad5421_channels[] = { 106dbdc025bSLars-Peter Clausen { 107dbdc025bSLars-Peter Clausen .type = IIO_CURRENT, 108dbdc025bSLars-Peter Clausen .indexed = 1, 109dbdc025bSLars-Peter Clausen .output = 1, 110dbdc025bSLars-Peter Clausen .channel = 0, 11131311c2aSJonathan Cameron .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | 11231311c2aSJonathan Cameron BIT(IIO_CHAN_INFO_CALIBSCALE) | 11331311c2aSJonathan Cameron BIT(IIO_CHAN_INFO_CALIBBIAS), 11431311c2aSJonathan Cameron .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | 11531311c2aSJonathan Cameron BIT(IIO_CHAN_INFO_OFFSET), 11649f82897SJonathan Cameron .scan_type = { 11749f82897SJonathan Cameron .sign = 'u', 11849f82897SJonathan Cameron .realbits = 16, 11949f82897SJonathan Cameron .storagebits = 16, 12049f82897SJonathan Cameron }, 1211eefd62bSLars-Peter Clausen .event_spec = ad5421_current_event, 1221eefd62bSLars-Peter Clausen .num_event_specs = ARRAY_SIZE(ad5421_current_event), 123dbdc025bSLars-Peter Clausen }, 124dbdc025bSLars-Peter Clausen { 125dbdc025bSLars-Peter Clausen .type = IIO_TEMP, 126dbdc025bSLars-Peter Clausen .channel = -1, 1271eefd62bSLars-Peter Clausen .event_spec = ad5421_temp_event, 1281eefd62bSLars-Peter Clausen .num_event_specs = ARRAY_SIZE(ad5421_temp_event), 129dbdc025bSLars-Peter Clausen }, 130dbdc025bSLars-Peter Clausen }; 131dbdc025bSLars-Peter Clausen 132dbdc025bSLars-Peter Clausen static int ad5421_write_unlocked(struct iio_dev *indio_dev, 133dbdc025bSLars-Peter Clausen unsigned int reg, unsigned int val) 134dbdc025bSLars-Peter Clausen { 135dbdc025bSLars-Peter Clausen struct ad5421_state *st = iio_priv(indio_dev); 136dbdc025bSLars-Peter Clausen 137dbdc025bSLars-Peter Clausen st->data[0].d32 = cpu_to_be32((reg << 16) | val); 138dbdc025bSLars-Peter Clausen 139dbdc025bSLars-Peter Clausen return spi_write(st->spi, &st->data[0].d8[1], 3); 140dbdc025bSLars-Peter Clausen } 141dbdc025bSLars-Peter Clausen 142dbdc025bSLars-Peter Clausen static int ad5421_write(struct iio_dev *indio_dev, unsigned int reg, 143dbdc025bSLars-Peter Clausen unsigned int val) 144dbdc025bSLars-Peter Clausen { 145dbdc025bSLars-Peter Clausen int ret; 146dbdc025bSLars-Peter Clausen 147dbdc025bSLars-Peter Clausen mutex_lock(&indio_dev->mlock); 148dbdc025bSLars-Peter Clausen ret = ad5421_write_unlocked(indio_dev, reg, val); 149dbdc025bSLars-Peter Clausen mutex_unlock(&indio_dev->mlock); 150dbdc025bSLars-Peter Clausen 151dbdc025bSLars-Peter Clausen return ret; 152dbdc025bSLars-Peter Clausen } 153dbdc025bSLars-Peter Clausen 154dbdc025bSLars-Peter Clausen static int ad5421_read(struct iio_dev *indio_dev, unsigned int reg) 155dbdc025bSLars-Peter Clausen { 156dbdc025bSLars-Peter Clausen struct ad5421_state *st = iio_priv(indio_dev); 157dbdc025bSLars-Peter Clausen int ret; 158dbdc025bSLars-Peter Clausen struct spi_transfer t[] = { 159dbdc025bSLars-Peter Clausen { 160dbdc025bSLars-Peter Clausen .tx_buf = &st->data[0].d8[1], 161dbdc025bSLars-Peter Clausen .len = 3, 162dbdc025bSLars-Peter Clausen .cs_change = 1, 163dbdc025bSLars-Peter Clausen }, { 164dbdc025bSLars-Peter Clausen .rx_buf = &st->data[1].d8[1], 165dbdc025bSLars-Peter Clausen .len = 3, 166dbdc025bSLars-Peter Clausen }, 167dbdc025bSLars-Peter Clausen }; 168dbdc025bSLars-Peter Clausen 169dbdc025bSLars-Peter Clausen mutex_lock(&indio_dev->mlock); 170dbdc025bSLars-Peter Clausen 171dbdc025bSLars-Peter Clausen st->data[0].d32 = cpu_to_be32((1 << 23) | (reg << 16)); 172dbdc025bSLars-Peter Clausen 17314543a00SLars-Peter Clausen ret = spi_sync_transfer(st->spi, t, ARRAY_SIZE(t)); 174dbdc025bSLars-Peter Clausen if (ret >= 0) 175dbdc025bSLars-Peter Clausen ret = be32_to_cpu(st->data[1].d32) & 0xffff; 176dbdc025bSLars-Peter Clausen 177dbdc025bSLars-Peter Clausen mutex_unlock(&indio_dev->mlock); 178dbdc025bSLars-Peter Clausen 179dbdc025bSLars-Peter Clausen return ret; 180dbdc025bSLars-Peter Clausen } 181dbdc025bSLars-Peter Clausen 182dbdc025bSLars-Peter Clausen static int ad5421_update_ctrl(struct iio_dev *indio_dev, unsigned int set, 183dbdc025bSLars-Peter Clausen unsigned int clr) 184dbdc025bSLars-Peter Clausen { 185dbdc025bSLars-Peter Clausen struct ad5421_state *st = iio_priv(indio_dev); 186dbdc025bSLars-Peter Clausen unsigned int ret; 187dbdc025bSLars-Peter Clausen 188dbdc025bSLars-Peter Clausen mutex_lock(&indio_dev->mlock); 189dbdc025bSLars-Peter Clausen 190dbdc025bSLars-Peter Clausen st->ctrl &= ~clr; 191dbdc025bSLars-Peter Clausen st->ctrl |= set; 192dbdc025bSLars-Peter Clausen 193dbdc025bSLars-Peter Clausen ret = ad5421_write_unlocked(indio_dev, AD5421_REG_CTRL, st->ctrl); 194dbdc025bSLars-Peter Clausen 195dbdc025bSLars-Peter Clausen mutex_unlock(&indio_dev->mlock); 196dbdc025bSLars-Peter Clausen 197dbdc025bSLars-Peter Clausen return ret; 198dbdc025bSLars-Peter Clausen } 199dbdc025bSLars-Peter Clausen 200dbdc025bSLars-Peter Clausen static irqreturn_t ad5421_fault_handler(int irq, void *data) 201dbdc025bSLars-Peter Clausen { 202dbdc025bSLars-Peter Clausen struct iio_dev *indio_dev = data; 203dbdc025bSLars-Peter Clausen struct ad5421_state *st = iio_priv(indio_dev); 204dbdc025bSLars-Peter Clausen unsigned int fault; 205dbdc025bSLars-Peter Clausen unsigned int old_fault = 0; 206dbdc025bSLars-Peter Clausen unsigned int events; 207dbdc025bSLars-Peter Clausen 208dbdc025bSLars-Peter Clausen fault = ad5421_read(indio_dev, AD5421_REG_FAULT); 209dbdc025bSLars-Peter Clausen if (!fault) 210dbdc025bSLars-Peter Clausen return IRQ_NONE; 211dbdc025bSLars-Peter Clausen 212dbdc025bSLars-Peter Clausen /* If we had a fault, this might mean that the DAC has lost its state 213dbdc025bSLars-Peter Clausen * and has been reset. Make sure that the control register actually 214dbdc025bSLars-Peter Clausen * contains what we expect it to contain. Otherwise the watchdog might 215dbdc025bSLars-Peter Clausen * be enabled and we get watchdog timeout faults, which will render the 216dbdc025bSLars-Peter Clausen * DAC unusable. */ 217dbdc025bSLars-Peter Clausen ad5421_update_ctrl(indio_dev, 0, 0); 218dbdc025bSLars-Peter Clausen 219dbdc025bSLars-Peter Clausen 220dbdc025bSLars-Peter Clausen /* The fault pin stays high as long as a fault condition is present and 221dbdc025bSLars-Peter Clausen * it is not possible to mask fault conditions. For certain fault 222dbdc025bSLars-Peter Clausen * conditions for example like over-temperature it takes some time 223dbdc025bSLars-Peter Clausen * until the fault condition disappears. If we would exit the interrupt 224dbdc025bSLars-Peter Clausen * handler immediately after handling the event it would be entered 225dbdc025bSLars-Peter Clausen * again instantly. Thus we fall back to polling in case we detect that 226dbdc025bSLars-Peter Clausen * a interrupt condition is still present. 227dbdc025bSLars-Peter Clausen */ 228dbdc025bSLars-Peter Clausen do { 229dbdc025bSLars-Peter Clausen /* 0xffff is a invalid value for the register and will only be 230dbdc025bSLars-Peter Clausen * read if there has been a communication error */ 231dbdc025bSLars-Peter Clausen if (fault == 0xffff) 232dbdc025bSLars-Peter Clausen fault = 0; 233dbdc025bSLars-Peter Clausen 234dbdc025bSLars-Peter Clausen /* we are only interested in new events */ 235dbdc025bSLars-Peter Clausen events = (old_fault ^ fault) & fault; 236dbdc025bSLars-Peter Clausen events &= st->fault_mask; 237dbdc025bSLars-Peter Clausen 238dbdc025bSLars-Peter Clausen if (events & AD5421_FAULT_OVER_CURRENT) { 239dbdc025bSLars-Peter Clausen iio_push_event(indio_dev, 240dbdc025bSLars-Peter Clausen IIO_UNMOD_EVENT_CODE(IIO_CURRENT, 241dbdc025bSLars-Peter Clausen 0, 242dbdc025bSLars-Peter Clausen IIO_EV_TYPE_THRESH, 243dbdc025bSLars-Peter Clausen IIO_EV_DIR_RISING), 244bc2b7dabSGregor Boirie iio_get_time_ns(indio_dev)); 245dbdc025bSLars-Peter Clausen } 246dbdc025bSLars-Peter Clausen 247dbdc025bSLars-Peter Clausen if (events & AD5421_FAULT_UNDER_CURRENT) { 248dbdc025bSLars-Peter Clausen iio_push_event(indio_dev, 249dbdc025bSLars-Peter Clausen IIO_UNMOD_EVENT_CODE(IIO_CURRENT, 250dbdc025bSLars-Peter Clausen 0, 251dbdc025bSLars-Peter Clausen IIO_EV_TYPE_THRESH, 252dbdc025bSLars-Peter Clausen IIO_EV_DIR_FALLING), 253bc2b7dabSGregor Boirie iio_get_time_ns(indio_dev)); 254dbdc025bSLars-Peter Clausen } 255dbdc025bSLars-Peter Clausen 256dbdc025bSLars-Peter Clausen if (events & AD5421_FAULT_TEMP_OVER_140) { 257dbdc025bSLars-Peter Clausen iio_push_event(indio_dev, 258dbdc025bSLars-Peter Clausen IIO_UNMOD_EVENT_CODE(IIO_TEMP, 259dbdc025bSLars-Peter Clausen 0, 260dbdc025bSLars-Peter Clausen IIO_EV_TYPE_MAG, 261dbdc025bSLars-Peter Clausen IIO_EV_DIR_RISING), 262bc2b7dabSGregor Boirie iio_get_time_ns(indio_dev)); 263dbdc025bSLars-Peter Clausen } 264dbdc025bSLars-Peter Clausen 265dbdc025bSLars-Peter Clausen old_fault = fault; 266dbdc025bSLars-Peter Clausen fault = ad5421_read(indio_dev, AD5421_REG_FAULT); 267dbdc025bSLars-Peter Clausen 268dbdc025bSLars-Peter Clausen /* still active? go to sleep for some time */ 269dbdc025bSLars-Peter Clausen if (fault & AD5421_FAULT_TRIGGER_IRQ) 270dbdc025bSLars-Peter Clausen msleep(1000); 271dbdc025bSLars-Peter Clausen 272dbdc025bSLars-Peter Clausen } while (fault & AD5421_FAULT_TRIGGER_IRQ); 273dbdc025bSLars-Peter Clausen 274dbdc025bSLars-Peter Clausen 275dbdc025bSLars-Peter Clausen return IRQ_HANDLED; 276dbdc025bSLars-Peter Clausen } 277dbdc025bSLars-Peter Clausen 278dbdc025bSLars-Peter Clausen static void ad5421_get_current_min_max(struct ad5421_state *st, 279dbdc025bSLars-Peter Clausen unsigned int *min, unsigned int *max) 280dbdc025bSLars-Peter Clausen { 281dbdc025bSLars-Peter Clausen /* The current range is configured using external pins, which are 282dbdc025bSLars-Peter Clausen * usually hard-wired and not run-time switchable. */ 283dbdc025bSLars-Peter Clausen switch (st->current_range) { 284dbdc025bSLars-Peter Clausen case AD5421_CURRENT_RANGE_4mA_20mA: 285dbdc025bSLars-Peter Clausen *min = 4000; 286dbdc025bSLars-Peter Clausen *max = 20000; 287dbdc025bSLars-Peter Clausen break; 288dbdc025bSLars-Peter Clausen case AD5421_CURRENT_RANGE_3mA8_21mA: 289dbdc025bSLars-Peter Clausen *min = 3800; 290dbdc025bSLars-Peter Clausen *max = 21000; 291dbdc025bSLars-Peter Clausen break; 292dbdc025bSLars-Peter Clausen case AD5421_CURRENT_RANGE_3mA2_24mA: 293dbdc025bSLars-Peter Clausen *min = 3200; 294dbdc025bSLars-Peter Clausen *max = 24000; 295dbdc025bSLars-Peter Clausen break; 296dbdc025bSLars-Peter Clausen default: 297dbdc025bSLars-Peter Clausen *min = 0; 298dbdc025bSLars-Peter Clausen *max = 1; 299dbdc025bSLars-Peter Clausen break; 300dbdc025bSLars-Peter Clausen } 301dbdc025bSLars-Peter Clausen } 302dbdc025bSLars-Peter Clausen 303dbdc025bSLars-Peter Clausen static inline unsigned int ad5421_get_offset(struct ad5421_state *st) 304dbdc025bSLars-Peter Clausen { 305dbdc025bSLars-Peter Clausen unsigned int min, max; 306dbdc025bSLars-Peter Clausen 307dbdc025bSLars-Peter Clausen ad5421_get_current_min_max(st, &min, &max); 308dbdc025bSLars-Peter Clausen return (min * (1 << 16)) / (max - min); 309dbdc025bSLars-Peter Clausen } 310dbdc025bSLars-Peter Clausen 311dbdc025bSLars-Peter Clausen static int ad5421_read_raw(struct iio_dev *indio_dev, 312dbdc025bSLars-Peter Clausen struct iio_chan_spec const *chan, int *val, int *val2, long m) 313dbdc025bSLars-Peter Clausen { 314dbdc025bSLars-Peter Clausen struct ad5421_state *st = iio_priv(indio_dev); 315bc7c49bcSLars-Peter Clausen unsigned int min, max; 316dbdc025bSLars-Peter Clausen int ret; 317dbdc025bSLars-Peter Clausen 318dbdc025bSLars-Peter Clausen if (chan->type != IIO_CURRENT) 319dbdc025bSLars-Peter Clausen return -EINVAL; 320dbdc025bSLars-Peter Clausen 321dbdc025bSLars-Peter Clausen switch (m) { 322dbdc025bSLars-Peter Clausen case IIO_CHAN_INFO_RAW: 323dbdc025bSLars-Peter Clausen ret = ad5421_read(indio_dev, AD5421_REG_DAC_DATA); 324dbdc025bSLars-Peter Clausen if (ret < 0) 325dbdc025bSLars-Peter Clausen return ret; 326dbdc025bSLars-Peter Clausen *val = ret; 327dbdc025bSLars-Peter Clausen return IIO_VAL_INT; 328dbdc025bSLars-Peter Clausen case IIO_CHAN_INFO_SCALE: 329bc7c49bcSLars-Peter Clausen ad5421_get_current_min_max(st, &min, &max); 330bc7c49bcSLars-Peter Clausen *val = max - min; 331bc7c49bcSLars-Peter Clausen *val2 = (1 << 16) * 1000; 332bc7c49bcSLars-Peter Clausen return IIO_VAL_FRACTIONAL; 333dbdc025bSLars-Peter Clausen case IIO_CHAN_INFO_OFFSET: 334dbdc025bSLars-Peter Clausen *val = ad5421_get_offset(st); 335dbdc025bSLars-Peter Clausen return IIO_VAL_INT; 336dbdc025bSLars-Peter Clausen case IIO_CHAN_INFO_CALIBBIAS: 337dbdc025bSLars-Peter Clausen ret = ad5421_read(indio_dev, AD5421_REG_OFFSET); 338dbdc025bSLars-Peter Clausen if (ret < 0) 339dbdc025bSLars-Peter Clausen return ret; 340dbdc025bSLars-Peter Clausen *val = ret - 32768; 341dbdc025bSLars-Peter Clausen return IIO_VAL_INT; 342dbdc025bSLars-Peter Clausen case IIO_CHAN_INFO_CALIBSCALE: 343dbdc025bSLars-Peter Clausen ret = ad5421_read(indio_dev, AD5421_REG_GAIN); 344dbdc025bSLars-Peter Clausen if (ret < 0) 345dbdc025bSLars-Peter Clausen return ret; 346dbdc025bSLars-Peter Clausen *val = ret; 347dbdc025bSLars-Peter Clausen return IIO_VAL_INT; 348dbdc025bSLars-Peter Clausen } 349dbdc025bSLars-Peter Clausen 350dbdc025bSLars-Peter Clausen return -EINVAL; 351dbdc025bSLars-Peter Clausen } 352dbdc025bSLars-Peter Clausen 353dbdc025bSLars-Peter Clausen static int ad5421_write_raw(struct iio_dev *indio_dev, 354dbdc025bSLars-Peter Clausen struct iio_chan_spec const *chan, int val, int val2, long mask) 355dbdc025bSLars-Peter Clausen { 356dbdc025bSLars-Peter Clausen const unsigned int max_val = 1 << 16; 357dbdc025bSLars-Peter Clausen 358dbdc025bSLars-Peter Clausen switch (mask) { 359dbdc025bSLars-Peter Clausen case IIO_CHAN_INFO_RAW: 360dbdc025bSLars-Peter Clausen if (val >= max_val || val < 0) 361dbdc025bSLars-Peter Clausen return -EINVAL; 362dbdc025bSLars-Peter Clausen 363dbdc025bSLars-Peter Clausen return ad5421_write(indio_dev, AD5421_REG_DAC_DATA, val); 364dbdc025bSLars-Peter Clausen case IIO_CHAN_INFO_CALIBBIAS: 365dbdc025bSLars-Peter Clausen val += 32768; 366dbdc025bSLars-Peter Clausen if (val >= max_val || val < 0) 367dbdc025bSLars-Peter Clausen return -EINVAL; 368dbdc025bSLars-Peter Clausen 369dbdc025bSLars-Peter Clausen return ad5421_write(indio_dev, AD5421_REG_OFFSET, val); 370dbdc025bSLars-Peter Clausen case IIO_CHAN_INFO_CALIBSCALE: 371dbdc025bSLars-Peter Clausen if (val >= max_val || val < 0) 372dbdc025bSLars-Peter Clausen return -EINVAL; 373dbdc025bSLars-Peter Clausen 374dbdc025bSLars-Peter Clausen return ad5421_write(indio_dev, AD5421_REG_GAIN, val); 375dbdc025bSLars-Peter Clausen default: 376dbdc025bSLars-Peter Clausen break; 377dbdc025bSLars-Peter Clausen } 378dbdc025bSLars-Peter Clausen 379dbdc025bSLars-Peter Clausen return -EINVAL; 380dbdc025bSLars-Peter Clausen } 381dbdc025bSLars-Peter Clausen 382dbdc025bSLars-Peter Clausen static int ad5421_write_event_config(struct iio_dev *indio_dev, 3831eefd62bSLars-Peter Clausen const struct iio_chan_spec *chan, enum iio_event_type type, 3841eefd62bSLars-Peter Clausen enum iio_event_direction dir, int state) 385dbdc025bSLars-Peter Clausen { 386dbdc025bSLars-Peter Clausen struct ad5421_state *st = iio_priv(indio_dev); 387dbdc025bSLars-Peter Clausen unsigned int mask; 388dbdc025bSLars-Peter Clausen 3891eefd62bSLars-Peter Clausen switch (chan->type) { 390dbdc025bSLars-Peter Clausen case IIO_CURRENT: 3911eefd62bSLars-Peter Clausen if (dir == IIO_EV_DIR_RISING) 392dbdc025bSLars-Peter Clausen mask = AD5421_FAULT_OVER_CURRENT; 393dbdc025bSLars-Peter Clausen else 394dbdc025bSLars-Peter Clausen mask = AD5421_FAULT_UNDER_CURRENT; 395dbdc025bSLars-Peter Clausen break; 396dbdc025bSLars-Peter Clausen case IIO_TEMP: 397dbdc025bSLars-Peter Clausen mask = AD5421_FAULT_TEMP_OVER_140; 398dbdc025bSLars-Peter Clausen break; 399dbdc025bSLars-Peter Clausen default: 400dbdc025bSLars-Peter Clausen return -EINVAL; 401dbdc025bSLars-Peter Clausen } 402dbdc025bSLars-Peter Clausen 403dbdc025bSLars-Peter Clausen mutex_lock(&indio_dev->mlock); 404dbdc025bSLars-Peter Clausen if (state) 405dbdc025bSLars-Peter Clausen st->fault_mask |= mask; 406dbdc025bSLars-Peter Clausen else 407dbdc025bSLars-Peter Clausen st->fault_mask &= ~mask; 408dbdc025bSLars-Peter Clausen mutex_unlock(&indio_dev->mlock); 409dbdc025bSLars-Peter Clausen 410dbdc025bSLars-Peter Clausen return 0; 411dbdc025bSLars-Peter Clausen } 412dbdc025bSLars-Peter Clausen 413dbdc025bSLars-Peter Clausen static int ad5421_read_event_config(struct iio_dev *indio_dev, 4141eefd62bSLars-Peter Clausen const struct iio_chan_spec *chan, enum iio_event_type type, 4151eefd62bSLars-Peter Clausen enum iio_event_direction dir) 416dbdc025bSLars-Peter Clausen { 417dbdc025bSLars-Peter Clausen struct ad5421_state *st = iio_priv(indio_dev); 418dbdc025bSLars-Peter Clausen unsigned int mask; 419dbdc025bSLars-Peter Clausen 4201eefd62bSLars-Peter Clausen switch (chan->type) { 421dbdc025bSLars-Peter Clausen case IIO_CURRENT: 4221eefd62bSLars-Peter Clausen if (dir == IIO_EV_DIR_RISING) 423dbdc025bSLars-Peter Clausen mask = AD5421_FAULT_OVER_CURRENT; 424dbdc025bSLars-Peter Clausen else 425dbdc025bSLars-Peter Clausen mask = AD5421_FAULT_UNDER_CURRENT; 426dbdc025bSLars-Peter Clausen break; 427dbdc025bSLars-Peter Clausen case IIO_TEMP: 428dbdc025bSLars-Peter Clausen mask = AD5421_FAULT_TEMP_OVER_140; 429dbdc025bSLars-Peter Clausen break; 430dbdc025bSLars-Peter Clausen default: 431dbdc025bSLars-Peter Clausen return -EINVAL; 432dbdc025bSLars-Peter Clausen } 433dbdc025bSLars-Peter Clausen 434dbdc025bSLars-Peter Clausen return (bool)(st->fault_mask & mask); 435dbdc025bSLars-Peter Clausen } 436dbdc025bSLars-Peter Clausen 4371eefd62bSLars-Peter Clausen static int ad5421_read_event_value(struct iio_dev *indio_dev, 4381eefd62bSLars-Peter Clausen const struct iio_chan_spec *chan, enum iio_event_type type, 4391eefd62bSLars-Peter Clausen enum iio_event_direction dir, enum iio_event_info info, int *val, 4401eefd62bSLars-Peter Clausen int *val2) 441dbdc025bSLars-Peter Clausen { 442dbdc025bSLars-Peter Clausen int ret; 443dbdc025bSLars-Peter Clausen 4441eefd62bSLars-Peter Clausen switch (chan->type) { 445dbdc025bSLars-Peter Clausen case IIO_CURRENT: 446dbdc025bSLars-Peter Clausen ret = ad5421_read(indio_dev, AD5421_REG_DAC_DATA); 447dbdc025bSLars-Peter Clausen if (ret < 0) 448dbdc025bSLars-Peter Clausen return ret; 449dbdc025bSLars-Peter Clausen *val = ret; 450dbdc025bSLars-Peter Clausen break; 451dbdc025bSLars-Peter Clausen case IIO_TEMP: 452dbdc025bSLars-Peter Clausen *val = 140000; 453dbdc025bSLars-Peter Clausen break; 454dbdc025bSLars-Peter Clausen default: 455dbdc025bSLars-Peter Clausen return -EINVAL; 456dbdc025bSLars-Peter Clausen } 457dbdc025bSLars-Peter Clausen 4581eefd62bSLars-Peter Clausen return IIO_VAL_INT; 459dbdc025bSLars-Peter Clausen } 460dbdc025bSLars-Peter Clausen 461dbdc025bSLars-Peter Clausen static const struct iio_info ad5421_info = { 462dbdc025bSLars-Peter Clausen .read_raw = ad5421_read_raw, 463dbdc025bSLars-Peter Clausen .write_raw = ad5421_write_raw, 464cb955852SLars-Peter Clausen .read_event_config = ad5421_read_event_config, 465cb955852SLars-Peter Clausen .write_event_config = ad5421_write_event_config, 466cb955852SLars-Peter Clausen .read_event_value = ad5421_read_event_value, 467dbdc025bSLars-Peter Clausen }; 468dbdc025bSLars-Peter Clausen 469fc52692cSGreg Kroah-Hartman static int ad5421_probe(struct spi_device *spi) 470dbdc025bSLars-Peter Clausen { 471dbdc025bSLars-Peter Clausen struct ad5421_platform_data *pdata = dev_get_platdata(&spi->dev); 472dbdc025bSLars-Peter Clausen struct iio_dev *indio_dev; 473dbdc025bSLars-Peter Clausen struct ad5421_state *st; 474dbdc025bSLars-Peter Clausen int ret; 475dbdc025bSLars-Peter Clausen 47662a308a6SSachin Kamat indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); 477dbdc025bSLars-Peter Clausen if (indio_dev == NULL) { 478dbdc025bSLars-Peter Clausen dev_err(&spi->dev, "Failed to allocate iio device\n"); 479dbdc025bSLars-Peter Clausen return -ENOMEM; 480dbdc025bSLars-Peter Clausen } 481dbdc025bSLars-Peter Clausen 482dbdc025bSLars-Peter Clausen st = iio_priv(indio_dev); 483dbdc025bSLars-Peter Clausen spi_set_drvdata(spi, indio_dev); 484dbdc025bSLars-Peter Clausen 485dbdc025bSLars-Peter Clausen st->spi = spi; 486dbdc025bSLars-Peter Clausen 487dbdc025bSLars-Peter Clausen indio_dev->dev.parent = &spi->dev; 488dbdc025bSLars-Peter Clausen indio_dev->name = "ad5421"; 489dbdc025bSLars-Peter Clausen indio_dev->info = &ad5421_info; 490dbdc025bSLars-Peter Clausen indio_dev->modes = INDIO_DIRECT_MODE; 491dbdc025bSLars-Peter Clausen indio_dev->channels = ad5421_channels; 492dbdc025bSLars-Peter Clausen indio_dev->num_channels = ARRAY_SIZE(ad5421_channels); 493dbdc025bSLars-Peter Clausen 494dbdc025bSLars-Peter Clausen st->ctrl = AD5421_CTRL_WATCHDOG_DISABLE | 495dbdc025bSLars-Peter Clausen AD5421_CTRL_AUTO_FAULT_READBACK; 496dbdc025bSLars-Peter Clausen 497dbdc025bSLars-Peter Clausen if (pdata) { 498dbdc025bSLars-Peter Clausen st->current_range = pdata->current_range; 499dbdc025bSLars-Peter Clausen if (pdata->external_vref) 500dbdc025bSLars-Peter Clausen st->ctrl |= AD5421_CTRL_PWR_DOWN_INT_VREF; 501dbdc025bSLars-Peter Clausen } else { 502dbdc025bSLars-Peter Clausen st->current_range = AD5421_CURRENT_RANGE_4mA_20mA; 503dbdc025bSLars-Peter Clausen } 504dbdc025bSLars-Peter Clausen 505dbdc025bSLars-Peter Clausen /* write initial ctrl register value */ 506dbdc025bSLars-Peter Clausen ad5421_update_ctrl(indio_dev, 0, 0); 507dbdc025bSLars-Peter Clausen 508dbdc025bSLars-Peter Clausen if (spi->irq) { 50962a308a6SSachin Kamat ret = devm_request_threaded_irq(&spi->dev, spi->irq, 510dbdc025bSLars-Peter Clausen NULL, 511dbdc025bSLars-Peter Clausen ad5421_fault_handler, 512dbdc025bSLars-Peter Clausen IRQF_TRIGGER_HIGH | IRQF_ONESHOT, 513dbdc025bSLars-Peter Clausen "ad5421 fault", 514dbdc025bSLars-Peter Clausen indio_dev); 515dbdc025bSLars-Peter Clausen if (ret) 51662a308a6SSachin Kamat return ret; 517dbdc025bSLars-Peter Clausen } 518dbdc025bSLars-Peter Clausen 519365736e7SSachin Kamat return devm_iio_device_register(&spi->dev, indio_dev); 520dbdc025bSLars-Peter Clausen } 521dbdc025bSLars-Peter Clausen 522dbdc025bSLars-Peter Clausen static struct spi_driver ad5421_driver = { 523dbdc025bSLars-Peter Clausen .driver = { 524dbdc025bSLars-Peter Clausen .name = "ad5421", 525dbdc025bSLars-Peter Clausen }, 526dbdc025bSLars-Peter Clausen .probe = ad5421_probe, 527dbdc025bSLars-Peter Clausen }; 528dbdc025bSLars-Peter Clausen module_spi_driver(ad5421_driver); 529dbdc025bSLars-Peter Clausen 530dbdc025bSLars-Peter Clausen MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); 531dbdc025bSLars-Peter Clausen MODULE_DESCRIPTION("Analog Devices AD5421 DAC"); 532dbdc025bSLars-Peter Clausen MODULE_LICENSE("GPL v2"); 533dbdc025bSLars-Peter Clausen MODULE_ALIAS("spi:ad5421"); 534