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