diff options
Diffstat (limited to 'drivers/staging/iio/adc/ad7606_core.c')
-rw-r--r-- | drivers/staging/iio/adc/ad7606_core.c | 277 |
1 files changed, 141 insertions, 136 deletions
diff --git a/drivers/staging/iio/adc/ad7606_core.c b/drivers/staging/iio/adc/ad7606_core.c index 459371ae4dcc..54423ab196fe 100644 --- a/drivers/staging/iio/adc/ad7606_core.c +++ b/drivers/staging/iio/adc/ad7606_core.c @@ -16,17 +16,17 @@ #include <linux/gpio.h> #include <linux/delay.h> #include <linux/sched.h> +#include <linux/module.h> #include "../iio.h" #include "../sysfs.h" -#include "../ring_generic.h" -#include "adc.h" +#include "../buffer_generic.h" #include "ad7606.h" int ad7606_reset(struct ad7606_state *st) { - if (st->have_reset) { + if (gpio_is_valid(st->pdata->gpio_reset)) { gpio_set_value(st->pdata->gpio_reset, 1); ndelay(100); /* t_reset >= 100ns */ gpio_set_value(st->pdata->gpio_reset, 0); @@ -48,7 +48,7 @@ static int ad7606_scan_direct(struct iio_dev *indio_dev, unsigned ch) if (ret) goto error_ret; - if (st->have_frstdata) { + if (gpio_is_valid(st->pdata->gpio_frstdata)) { ret = st->bops->read_block(st->dev, 1, st->data); if (ret) goto error_ret; @@ -90,7 +90,7 @@ static int ad7606_read_raw(struct iio_dev *indio_dev, switch (m) { case 0: mutex_lock(&indio_dev->mlock); - if (iio_ring_enabled(indio_dev)) + if (iio_buffer_enabled(indio_dev)) ret = ad7606_scan_from_ring(indio_dev, chan->address); else ret = ad7606_scan_direct(indio_dev, chan->address); @@ -140,9 +140,9 @@ static ssize_t ad7606_store_range(struct device *dev, return count; } -static IIO_DEVICE_ATTR(range, S_IRUGO | S_IWUSR, \ +static IIO_DEVICE_ATTR(in_voltage_range, S_IRUGO | S_IWUSR, \ ad7606_show_range, ad7606_store_range, 0); -static IIO_CONST_ATTR(range_available, "5000 10000"); +static IIO_CONST_ATTR(in_voltage_range_available, "5000 10000"); static ssize_t ad7606_show_oversampling_ratio(struct device *dev, struct device_attribute *attr, char *buf) @@ -198,8 +198,8 @@ static IIO_DEVICE_ATTR(oversampling_ratio, S_IRUGO | S_IWUSR, static IIO_CONST_ATTR(oversampling_ratio_available, "0 2 4 8 16 32 64"); static struct attribute *ad7606_attributes[] = { - &iio_dev_attr_range.dev_attr.attr, - &iio_const_attr_range_available.dev_attr.attr, + &iio_dev_attr_in_voltage_range.dev_attr.attr, + &iio_const_attr_in_voltage_range_available.dev_attr.attr, &iio_dev_attr_oversampling_ratio.dev_attr.attr, &iio_const_attr_oversampling_ratio_available.dev_attr.attr, NULL, @@ -214,15 +214,18 @@ static mode_t ad7606_attr_is_visible(struct kobject *kobj, mode_t mode = attr->mode; - if (!st->have_os && - (attr == &iio_dev_attr_oversampling_ratio.dev_attr.attr || - attr == - &iio_const_attr_oversampling_ratio_available.dev_attr.attr)) + if (!(gpio_is_valid(st->pdata->gpio_os0) && + gpio_is_valid(st->pdata->gpio_os1) && + gpio_is_valid(st->pdata->gpio_os2)) && + (attr == &iio_dev_attr_oversampling_ratio.dev_attr.attr || + attr == + &iio_const_attr_oversampling_ratio_available.dev_attr.attr)) + mode = 0; + else if (!gpio_is_valid(st->pdata->gpio_range) && + (attr == &iio_dev_attr_in_voltage_range.dev_attr.attr || + attr == + &iio_const_attr_in_voltage_range_available.dev_attr.attr)) mode = 0; - else if (!st->have_range && - (attr == &iio_dev_attr_range.dev_attr.attr || - attr == &iio_const_attr_range_available.dev_attr.attr)) - mode = 0; return mode; } @@ -232,69 +235,43 @@ static const struct attribute_group ad7606_attribute_group = { .is_visible = ad7606_attr_is_visible, }; +#define AD7606_CHANNEL(num) \ + { \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .channel = num, \ + .address = num, \ + .scan_index = num, \ + .scan_type = IIO_ST('s', 16, 16, 0), \ + } + static struct iio_chan_spec ad7606_8_channels[] = { - IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 0, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - 0, 0, IIO_ST('s', 16, 16, 0), 0), - IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 1, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - 1, 1, IIO_ST('s', 16, 16, 0), 0), - IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 2, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - 2, 2, IIO_ST('s', 16, 16, 0), 0), - IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 3, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - 3, 3, IIO_ST('s', 16, 16, 0), 0), - IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 4, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - 4, 4, IIO_ST('s', 16, 16, 0), 0), - IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 5, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - 5, 5, IIO_ST('s', 16, 16, 0), 0), - IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 6, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - 6, 6, IIO_ST('s', 16, 16, 0), 0), - IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 7, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - 7, 7, IIO_ST('s', 16, 16, 0), 0), + AD7606_CHANNEL(0), + AD7606_CHANNEL(1), + AD7606_CHANNEL(2), + AD7606_CHANNEL(3), + AD7606_CHANNEL(4), + AD7606_CHANNEL(5), + AD7606_CHANNEL(6), + AD7606_CHANNEL(7), IIO_CHAN_SOFT_TIMESTAMP(8), }; static struct iio_chan_spec ad7606_6_channels[] = { - IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 0, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - 0, 0, IIO_ST('s', 16, 16, 0), 0), - IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 1, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - 1, 1, IIO_ST('s', 16, 16, 0), 0), - IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 2, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - 2, 2, IIO_ST('s', 16, 16, 0), 0), - IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 3, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - 3, 3, IIO_ST('s', 16, 16, 0), 0), - IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 4, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - 4, 4, IIO_ST('s', 16, 16, 0), 0), - IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 5, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - 5, 5, IIO_ST('s', 16, 16, 0), 0), + AD7606_CHANNEL(0), + AD7606_CHANNEL(1), + AD7606_CHANNEL(2), + AD7606_CHANNEL(3), + AD7606_CHANNEL(4), + AD7606_CHANNEL(5), IIO_CHAN_SOFT_TIMESTAMP(6), }; static struct iio_chan_spec ad7606_4_channels[] = { - IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 0, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - 0, 0, IIO_ST('s', 16, 16, 0), 0), - IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 1, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - 1, 1, IIO_ST('s', 16, 16, 0), 0), - IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 2, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - 2, 2, IIO_ST('s', 16, 16, 0), 0), - IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 3, 0, - (1 << IIO_CHAN_INFO_SCALE_SHARED), - 3, 3, IIO_ST('s', 16, 16, 0), 0), + AD7606_CHANNEL(0), + AD7606_CHANNEL(1), + AD7606_CHANNEL(2), + AD7606_CHANNEL(3), IIO_CHAN_SOFT_TIMESTAMP(4), }; @@ -346,64 +323,96 @@ static int ad7606_request_gpios(struct ad7606_state *st) }; int ret; - ret = gpio_request_one(st->pdata->gpio_convst, GPIOF_OUT_INIT_LOW, - "AD7606_CONVST"); - if (ret) { - dev_err(st->dev, "failed to request GPIO CONVST\n"); - return ret; + if (gpio_is_valid(st->pdata->gpio_convst)) { + ret = gpio_request_one(st->pdata->gpio_convst, + GPIOF_OUT_INIT_LOW, + "AD7606_CONVST"); + if (ret) { + dev_err(st->dev, "failed to request GPIO CONVST\n"); + goto error_ret; + } + } else { + ret = -EIO; + goto error_ret; } - ret = gpio_request_array(gpio_array, ARRAY_SIZE(gpio_array)); - if (!ret) { - st->have_os = true; + if (gpio_is_valid(st->pdata->gpio_os0) && + gpio_is_valid(st->pdata->gpio_os1) && + gpio_is_valid(st->pdata->gpio_os2)) { + ret = gpio_request_array(gpio_array, ARRAY_SIZE(gpio_array)); + if (ret < 0) + goto error_free_convst; } - ret = gpio_request_one(st->pdata->gpio_reset, GPIOF_OUT_INIT_LOW, - "AD7606_RESET"); - if (!ret) - st->have_reset = true; - - ret = gpio_request_one(st->pdata->gpio_range, GPIOF_DIR_OUT | - ((st->range == 10000) ? GPIOF_INIT_HIGH : - GPIOF_INIT_LOW), "AD7606_RANGE"); - if (!ret) - st->have_range = true; + if (gpio_is_valid(st->pdata->gpio_reset)) { + ret = gpio_request_one(st->pdata->gpio_reset, + GPIOF_OUT_INIT_LOW, + "AD7606_RESET"); + if (ret < 0) + goto error_free_os; + } - ret = gpio_request_one(st->pdata->gpio_stby, GPIOF_OUT_INIT_HIGH, - "AD7606_STBY"); - if (!ret) - st->have_stby = true; + if (gpio_is_valid(st->pdata->gpio_range)) { + ret = gpio_request_one(st->pdata->gpio_range, GPIOF_DIR_OUT | + ((st->range == 10000) ? GPIOF_INIT_HIGH : + GPIOF_INIT_LOW), "AD7606_RANGE"); + if (ret < 0) + goto error_free_reset; + } + if (gpio_is_valid(st->pdata->gpio_stby)) { + ret = gpio_request_one(st->pdata->gpio_stby, + GPIOF_OUT_INIT_HIGH, + "AD7606_STBY"); + if (ret < 0) + goto error_free_range; + } if (gpio_is_valid(st->pdata->gpio_frstdata)) { ret = gpio_request_one(st->pdata->gpio_frstdata, GPIOF_IN, "AD7606_FRSTDATA"); - if (!ret) - st->have_frstdata = true; + if (ret < 0) + goto error_free_stby; } return 0; + +error_free_stby: + if (gpio_is_valid(st->pdata->gpio_stby)) + gpio_free(st->pdata->gpio_stby); +error_free_range: + if (gpio_is_valid(st->pdata->gpio_range)) + gpio_free(st->pdata->gpio_range); +error_free_reset: + if (gpio_is_valid(st->pdata->gpio_reset)) + gpio_free(st->pdata->gpio_reset); +error_free_os: + if (gpio_is_valid(st->pdata->gpio_os0) && + gpio_is_valid(st->pdata->gpio_os1) && + gpio_is_valid(st->pdata->gpio_os2)) + gpio_free_array(gpio_array, ARRAY_SIZE(gpio_array)); +error_free_convst: + gpio_free(st->pdata->gpio_convst); +error_ret: + return ret; } static void ad7606_free_gpios(struct ad7606_state *st) { - if (st->have_range) - gpio_free(st->pdata->gpio_range); - - if (st->have_stby) + if (gpio_is_valid(st->pdata->gpio_frstdata)) + gpio_free(st->pdata->gpio_frstdata); + if (gpio_is_valid(st->pdata->gpio_stby)) gpio_free(st->pdata->gpio_stby); - - if (st->have_os) { - gpio_free(st->pdata->gpio_os0); - gpio_free(st->pdata->gpio_os1); + if (gpio_is_valid(st->pdata->gpio_range)) + gpio_free(st->pdata->gpio_range); + if (gpio_is_valid(st->pdata->gpio_reset)) + gpio_free(st->pdata->gpio_reset); + if (gpio_is_valid(st->pdata->gpio_os0) && + gpio_is_valid(st->pdata->gpio_os1) && + gpio_is_valid(st->pdata->gpio_os2)) { gpio_free(st->pdata->gpio_os2); + gpio_free(st->pdata->gpio_os1); + gpio_free(st->pdata->gpio_os0); } - - if (st->have_reset) - gpio_free(st->pdata->gpio_reset); - - if (st->have_frstdata) - gpio_free(st->pdata->gpio_frstdata); - gpio_free(st->pdata->gpio_convst); } @@ -415,7 +424,7 @@ static irqreturn_t ad7606_interrupt(int irq, void *dev_id) struct iio_dev *indio_dev = dev_id; struct ad7606_state *st = iio_priv(indio_dev); - if (iio_ring_enabled(indio_dev)) { + if (iio_buffer_enabled(indio_dev)) { if (!work_pending(&st->poll_work)) schedule_work(&st->poll_work); } else { @@ -439,7 +448,7 @@ struct iio_dev *ad7606_probe(struct device *dev, int irq, { struct ad7606_platform_data *pdata = dev->platform_data; struct ad7606_state *st; - int ret, regdone = 0; + int ret; struct iio_dev *indio_dev = iio_allocate_device(sizeof(*st)); if (indio_dev == NULL) { @@ -450,8 +459,6 @@ struct iio_dev *ad7606_probe(struct device *dev, int irq, st = iio_priv(indio_dev); st->dev = dev; - st->id = id; - st->irq = irq; st->bops = bops; st->base_address = base_address; st->range = pdata->default_range == 10000 ? 10000 : 5000; @@ -492,7 +499,7 @@ struct iio_dev *ad7606_probe(struct device *dev, int irq, if (ret) dev_warn(st->dev, "failed to RESET: no RESET GPIO specified\n"); - ret = request_irq(st->irq, ad7606_interrupt, + ret = request_irq(irq, ad7606_interrupt, IRQF_TRIGGER_FALLING, st->chip_info->name, indio_dev); if (ret) goto error_free_gpios; @@ -501,24 +508,24 @@ struct iio_dev *ad7606_probe(struct device *dev, int irq, if (ret) goto error_free_irq; - ret = iio_device_register(indio_dev); - if (ret) - goto error_free_irq; - regdone = 1; - - ret = iio_ring_buffer_register_ex(indio_dev->ring, 0, - indio_dev->channels, - indio_dev->num_channels); + ret = iio_buffer_register(indio_dev, + indio_dev->channels, + indio_dev->num_channels); if (ret) goto error_cleanup_ring; + ret = iio_device_register(indio_dev); + if (ret) + goto error_unregister_ring; return indio_dev; +error_unregister_ring: + iio_buffer_unregister(indio_dev); error_cleanup_ring: ad7606_ring_cleanup(indio_dev); error_free_irq: - free_irq(st->irq, indio_dev); + free_irq(irq, indio_dev); error_free_gpios: ad7606_free_gpios(st); @@ -529,29 +536,27 @@ error_disable_reg: error_put_reg: if (!IS_ERR(st->reg)) regulator_put(st->reg); - if (regdone) - iio_device_unregister(indio_dev); - else - iio_free_device(indio_dev); + iio_free_device(indio_dev); error_ret: return ERR_PTR(ret); } -int ad7606_remove(struct iio_dev *indio_dev) +int ad7606_remove(struct iio_dev *indio_dev, int irq) { struct ad7606_state *st = iio_priv(indio_dev); - iio_ring_buffer_unregister(indio_dev->ring); + iio_device_unregister(indio_dev); + iio_buffer_unregister(indio_dev); ad7606_ring_cleanup(indio_dev); - free_irq(st->irq, indio_dev); + free_irq(irq, indio_dev); if (!IS_ERR(st->reg)) { regulator_disable(st->reg); regulator_put(st->reg); } ad7606_free_gpios(st); - iio_device_unregister(indio_dev); + iio_free_device(indio_dev); return 0; } @@ -560,8 +565,8 @@ void ad7606_suspend(struct iio_dev *indio_dev) { struct ad7606_state *st = iio_priv(indio_dev); - if (st->have_stby) { - if (st->have_range) + if (gpio_is_valid(st->pdata->gpio_stby)) { + if (gpio_is_valid(st->pdata->gpio_range)) gpio_set_value(st->pdata->gpio_range, 1); gpio_set_value(st->pdata->gpio_stby, 0); } @@ -571,8 +576,8 @@ void ad7606_resume(struct iio_dev *indio_dev) { struct ad7606_state *st = iio_priv(indio_dev); - if (st->have_stby) { - if (st->have_range) + if (gpio_is_valid(st->pdata->gpio_stby)) { + if (gpio_is_valid(st->pdata->gpio_range)) gpio_set_value(st->pdata->gpio_range, st->range == 10000); |