diff options
Diffstat (limited to 'drivers/iio/dac/ad5421.c')
| -rw-r--r-- | drivers/iio/dac/ad5421.c | 154 |
1 files changed, 76 insertions, 78 deletions
diff --git a/drivers/iio/dac/ad5421.c b/drivers/iio/dac/ad5421.c index 98f24407c3ce..d9d7031c4432 100644 --- a/drivers/iio/dac/ad5421.c +++ b/drivers/iio/dac/ad5421.c @@ -1,9 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * AD5421 Digital to analog converters driver * * Copyright 2011 Analog Devices Inc. - * - * Licensed under the GPL-2. */ #include <linux/device.h> @@ -63,21 +62,46 @@ * @current_range: current range which the device is configured for * @data: spi transfer buffers * @fault_mask: software masking of events + * @lock: lock to protect the data buffer during SPI ops */ struct ad5421_state { struct spi_device *spi; unsigned int ctrl; enum ad5421_current_range current_range; unsigned int fault_mask; + struct mutex lock; /* - * DMA (thus cache coherency maintenance) requires the + * DMA (thus cache coherency maintenance) may require the * transfer buffers to live in their own cache lines. */ union { - u32 d32; + __be32 d32; u8 d8[4]; - } data[2] ____cacheline_aligned; + } data[2] __aligned(IIO_DMA_MINALIGN); +}; + +static const struct iio_event_spec ad5421_current_event[] = { + { + .type = IIO_EV_TYPE_THRESH, + .dir = IIO_EV_DIR_RISING, + .mask_separate = BIT(IIO_EV_INFO_VALUE) | + BIT(IIO_EV_INFO_ENABLE), + }, { + .type = IIO_EV_TYPE_THRESH, + .dir = IIO_EV_DIR_FALLING, + .mask_separate = BIT(IIO_EV_INFO_VALUE) | + BIT(IIO_EV_INFO_ENABLE), + }, +}; + +static const struct iio_event_spec ad5421_temp_event[] = { + { + .type = IIO_EV_TYPE_THRESH, + .dir = IIO_EV_DIR_RISING, + .mask_separate = BIT(IIO_EV_INFO_VALUE) | + BIT(IIO_EV_INFO_ENABLE), + }, }; static const struct iio_chan_spec ad5421_channels[] = { @@ -91,14 +115,19 @@ static const struct iio_chan_spec ad5421_channels[] = { BIT(IIO_CHAN_INFO_CALIBBIAS), .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_OFFSET), - .scan_type = IIO_ST('u', 16, 16, 0), - .event_mask = IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING) | - IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING), + .scan_type = { + .sign = 'u', + .realbits = 16, + .storagebits = 16, + }, + .event_spec = ad5421_current_event, + .num_event_specs = ARRAY_SIZE(ad5421_current_event), }, { .type = IIO_TEMP, .channel = -1, - .event_mask = IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING), + .event_spec = ad5421_temp_event, + .num_event_specs = ARRAY_SIZE(ad5421_temp_event), }, }; @@ -115,11 +144,12 @@ static int ad5421_write_unlocked(struct iio_dev *indio_dev, static int ad5421_write(struct iio_dev *indio_dev, unsigned int reg, unsigned int val) { + struct ad5421_state *st = iio_priv(indio_dev); int ret; - mutex_lock(&indio_dev->mlock); + mutex_lock(&st->lock); ret = ad5421_write_unlocked(indio_dev, reg, val); - mutex_unlock(&indio_dev->mlock); + mutex_unlock(&st->lock); return ret; } @@ -139,7 +169,7 @@ static int ad5421_read(struct iio_dev *indio_dev, unsigned int reg) }, }; - mutex_lock(&indio_dev->mlock); + mutex_lock(&st->lock); st->data[0].d32 = cpu_to_be32((1 << 23) | (reg << 16)); @@ -147,7 +177,7 @@ static int ad5421_read(struct iio_dev *indio_dev, unsigned int reg) if (ret >= 0) ret = be32_to_cpu(st->data[1].d32) & 0xffff; - mutex_unlock(&indio_dev->mlock); + mutex_unlock(&st->lock); return ret; } @@ -156,16 +186,16 @@ static int ad5421_update_ctrl(struct iio_dev *indio_dev, unsigned int set, unsigned int clr) { struct ad5421_state *st = iio_priv(indio_dev); - unsigned int ret; + int ret; - mutex_lock(&indio_dev->mlock); + mutex_lock(&st->lock); st->ctrl &= ~clr; st->ctrl |= set; ret = ad5421_write_unlocked(indio_dev, AD5421_REG_CTRL, st->ctrl); - mutex_unlock(&indio_dev->mlock); + mutex_unlock(&st->lock); return ret; } @@ -214,7 +244,7 @@ static irqreturn_t ad5421_fault_handler(int irq, void *data) 0, IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING), - iio_get_time_ns()); + iio_get_time_ns(indio_dev)); } if (events & AD5421_FAULT_UNDER_CURRENT) { @@ -223,7 +253,7 @@ static irqreturn_t ad5421_fault_handler(int irq, void *data) 0, IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING), - iio_get_time_ns()); + iio_get_time_ns(indio_dev)); } if (events & AD5421_FAULT_TEMP_OVER_140) { @@ -232,7 +262,7 @@ static irqreturn_t ad5421_fault_handler(int irq, void *data) 0, IIO_EV_TYPE_MAG, IIO_EV_DIR_RISING), - iio_get_time_ns()); + iio_get_time_ns(indio_dev)); } old_fault = fault; @@ -281,18 +311,11 @@ static inline unsigned int ad5421_get_offset(struct ad5421_state *st) return (min * (1 << 16)) / (max - min); } -static inline unsigned int ad5421_get_scale(struct ad5421_state *st) -{ - unsigned int min, max; - - ad5421_get_current_min_max(st, &min, &max); - return ((max - min) * 1000) / (1 << 16); -} - static int ad5421_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long m) { struct ad5421_state *st = iio_priv(indio_dev); + unsigned int min, max; int ret; if (chan->type != IIO_CURRENT) @@ -306,9 +329,10 @@ static int ad5421_read_raw(struct iio_dev *indio_dev, *val = ret; return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: - *val = 0; - *val2 = ad5421_get_scale(st); - return IIO_VAL_INT_PLUS_MICRO; + ad5421_get_current_min_max(st, &min, &max); + *val = max - min; + *val2 = (1 << 16) * 1000; + return IIO_VAL_FRACTIONAL; case IIO_CHAN_INFO_OFFSET: *val = ad5421_get_offset(st); return IIO_VAL_INT; @@ -359,15 +383,15 @@ static int ad5421_write_raw(struct iio_dev *indio_dev, } static int ad5421_write_event_config(struct iio_dev *indio_dev, - u64 event_code, int state) + const struct iio_chan_spec *chan, enum iio_event_type type, + enum iio_event_direction dir, bool state) { struct ad5421_state *st = iio_priv(indio_dev); unsigned int mask; - switch (IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event_code)) { + switch (chan->type) { case IIO_CURRENT: - if (IIO_EVENT_CODE_EXTRACT_DIR(event_code) == - IIO_EV_DIR_RISING) + if (dir == IIO_EV_DIR_RISING) mask = AD5421_FAULT_OVER_CURRENT; else mask = AD5421_FAULT_UNDER_CURRENT; @@ -379,26 +403,26 @@ static int ad5421_write_event_config(struct iio_dev *indio_dev, return -EINVAL; } - mutex_lock(&indio_dev->mlock); + mutex_lock(&st->lock); if (state) st->fault_mask |= mask; else st->fault_mask &= ~mask; - mutex_unlock(&indio_dev->mlock); + mutex_unlock(&st->lock); return 0; } static int ad5421_read_event_config(struct iio_dev *indio_dev, - u64 event_code) + const struct iio_chan_spec *chan, enum iio_event_type type, + enum iio_event_direction dir) { struct ad5421_state *st = iio_priv(indio_dev); unsigned int mask; - switch (IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event_code)) { + switch (chan->type) { case IIO_CURRENT: - if (IIO_EVENT_CODE_EXTRACT_DIR(event_code) == - IIO_EV_DIR_RISING) + if (dir == IIO_EV_DIR_RISING) mask = AD5421_FAULT_OVER_CURRENT; else mask = AD5421_FAULT_UNDER_CURRENT; @@ -413,12 +437,14 @@ static int ad5421_read_event_config(struct iio_dev *indio_dev, return (bool)(st->fault_mask & mask); } -static int ad5421_read_event_value(struct iio_dev *indio_dev, u64 event_code, - int *val) +static int ad5421_read_event_value(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, enum iio_event_type type, + enum iio_event_direction dir, enum iio_event_info info, int *val, + int *val2) { int ret; - switch (IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event_code)) { + switch (chan->type) { case IIO_CURRENT: ret = ad5421_read(indio_dev, AD5421_REG_DAC_DATA); if (ret < 0) @@ -432,7 +458,7 @@ static int ad5421_read_event_value(struct iio_dev *indio_dev, u64 event_code, return -EINVAL; } - return 0; + return IIO_VAL_INT; } static const struct iio_info ad5421_info = { @@ -441,7 +467,6 @@ static const struct iio_info ad5421_info = { .read_event_config = ad5421_read_event_config, .write_event_config = ad5421_write_event_config, .read_event_value = ad5421_read_event_value, - .driver_module = THIS_MODULE, }; static int ad5421_probe(struct spi_device *spi) @@ -451,7 +476,7 @@ static int ad5421_probe(struct spi_device *spi) struct ad5421_state *st; int ret; - indio_dev = iio_device_alloc(sizeof(*st)); + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); if (indio_dev == NULL) { dev_err(&spi->dev, "Failed to allocate iio device\n"); return -ENOMEM; @@ -462,13 +487,14 @@ static int ad5421_probe(struct spi_device *spi) st->spi = spi; - indio_dev->dev.parent = &spi->dev; indio_dev->name = "ad5421"; indio_dev->info = &ad5421_info; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = ad5421_channels; indio_dev->num_channels = ARRAY_SIZE(ad5421_channels); + mutex_init(&st->lock); + st->ctrl = AD5421_CTRL_WATCHDOG_DISABLE | AD5421_CTRL_AUTO_FAULT_READBACK; @@ -484,52 +510,24 @@ static int ad5421_probe(struct spi_device *spi) ad5421_update_ctrl(indio_dev, 0, 0); if (spi->irq) { - ret = request_threaded_irq(spi->irq, + ret = devm_request_threaded_irq(&spi->dev, spi->irq, NULL, ad5421_fault_handler, IRQF_TRIGGER_HIGH | IRQF_ONESHOT, "ad5421 fault", indio_dev); if (ret) - goto error_free; - } - - ret = iio_device_register(indio_dev); - if (ret) { - dev_err(&spi->dev, "Failed to register iio device: %d\n", ret); - goto error_free_irq; + return ret; } - return 0; - -error_free_irq: - if (spi->irq) - free_irq(spi->irq, indio_dev); -error_free: - iio_device_free(indio_dev); - - return ret; -} - -static int ad5421_remove(struct spi_device *spi) -{ - struct iio_dev *indio_dev = spi_get_drvdata(spi); - - iio_device_unregister(indio_dev); - if (spi->irq) - free_irq(spi->irq, indio_dev); - iio_device_free(indio_dev); - - return 0; + return devm_iio_device_register(&spi->dev, indio_dev); } static struct spi_driver ad5421_driver = { .driver = { .name = "ad5421", - .owner = THIS_MODULE, }, .probe = ad5421_probe, - .remove = ad5421_remove, }; module_spi_driver(ad5421_driver); |
