summaryrefslogtreecommitdiff
path: root/drivers/iio/adc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/iio/adc')
-rw-r--r--drivers/iio/adc/ad7793.c4
-rw-r--r--drivers/iio/adc/ad_sigma_delta.c28
-rw-r--r--drivers/iio/adc/axp288_adc.c32
-rw-r--r--drivers/iio/adc/fsl-imx25-gcq.c1
-rw-r--r--drivers/iio/adc/mcp320x.c25
-rw-r--r--drivers/iio/adc/ti-ads1015.c123
-rw-r--r--drivers/iio/adc/twl4030-madc.c10
-rw-r--r--drivers/iio/adc/vf610_adc.c2
-rw-r--r--drivers/iio/adc/xilinx-xadc-core.c6
9 files changed, 131 insertions, 100 deletions
diff --git a/drivers/iio/adc/ad7793.c b/drivers/iio/adc/ad7793.c
index e6706a0..47c3d7f 100644
--- a/drivers/iio/adc/ad7793.c
+++ b/drivers/iio/adc/ad7793.c
@@ -257,7 +257,7 @@ static int ad7793_setup(struct iio_dev *indio_dev,
unsigned int vref_mv)
{
struct ad7793_state *st = iio_priv(indio_dev);
- int i, ret = -1;
+ int i, ret;
unsigned long long scale_uv;
u32 id;
@@ -266,7 +266,7 @@ static int ad7793_setup(struct iio_dev *indio_dev,
return ret;
/* reset the serial interface */
- ret = spi_write(st->sd.spi, (u8 *)&ret, sizeof(ret));
+ ret = ad_sd_reset(&st->sd, 32);
if (ret < 0)
goto out;
usleep_range(500, 2000); /* Wait for at least 500us */
diff --git a/drivers/iio/adc/ad_sigma_delta.c b/drivers/iio/adc/ad_sigma_delta.c
index d10bd0c..22c4c17 100644
--- a/drivers/iio/adc/ad_sigma_delta.c
+++ b/drivers/iio/adc/ad_sigma_delta.c
@@ -177,6 +177,34 @@ out:
}
EXPORT_SYMBOL_GPL(ad_sd_read_reg);
+/**
+ * ad_sd_reset() - Reset the serial interface
+ *
+ * @sigma_delta: The sigma delta device
+ * @reset_length: Number of SCLKs with DIN = 1
+ *
+ * Returns 0 on success, an error code otherwise.
+ **/
+int ad_sd_reset(struct ad_sigma_delta *sigma_delta,
+ unsigned int reset_length)
+{
+ uint8_t *buf;
+ unsigned int size;
+ int ret;
+
+ size = DIV_ROUND_UP(reset_length, 8);
+ buf = kcalloc(size, sizeof(*buf), GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ memset(buf, 0xff, size);
+ ret = spi_write(sigma_delta->spi, buf, size);
+ kfree(buf);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(ad_sd_reset);
+
static int ad_sd_calibrate(struct ad_sigma_delta *sigma_delta,
unsigned int mode, unsigned int channel)
{
diff --git a/drivers/iio/adc/axp288_adc.c b/drivers/iio/adc/axp288_adc.c
index 7fd2494..64799ad 100644
--- a/drivers/iio/adc/axp288_adc.c
+++ b/drivers/iio/adc/axp288_adc.c
@@ -28,8 +28,6 @@
#include <linux/iio/driver.h>
#define AXP288_ADC_EN_MASK 0xF1
-#define AXP288_ADC_TS_PIN_GPADC 0xF2
-#define AXP288_ADC_TS_PIN_ON 0xF3
enum axp288_adc_id {
AXP288_ADC_TS,
@@ -123,16 +121,6 @@ static int axp288_adc_read_channel(int *val, unsigned long address,
return IIO_VAL_INT;
}
-static int axp288_adc_set_ts(struct regmap *regmap, unsigned int mode,
- unsigned long address)
-{
- /* channels other than GPADC do not need to switch TS pin */
- if (address != AXP288_GP_ADC_H)
- return 0;
-
- return regmap_write(regmap, AXP288_ADC_TS_PIN_CTRL, mode);
-}
-
static int axp288_adc_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long mask)
@@ -143,16 +131,7 @@ static int axp288_adc_read_raw(struct iio_dev *indio_dev,
mutex_lock(&indio_dev->mlock);
switch (mask) {
case IIO_CHAN_INFO_RAW:
- if (axp288_adc_set_ts(info->regmap, AXP288_ADC_TS_PIN_GPADC,
- chan->address)) {
- dev_err(&indio_dev->dev, "GPADC mode\n");
- ret = -EINVAL;
- break;
- }
ret = axp288_adc_read_channel(val, chan->address, info->regmap);
- if (axp288_adc_set_ts(info->regmap, AXP288_ADC_TS_PIN_ON,
- chan->address))
- dev_err(&indio_dev->dev, "TS pin restore\n");
break;
default:
ret = -EINVAL;
@@ -162,15 +141,6 @@ static int axp288_adc_read_raw(struct iio_dev *indio_dev,
return ret;
}
-static int axp288_adc_set_state(struct regmap *regmap)
-{
- /* ADC should be always enabled for internal FG to function */
- if (regmap_write(regmap, AXP288_ADC_TS_PIN_CTRL, AXP288_ADC_TS_PIN_ON))
- return -EIO;
-
- return regmap_write(regmap, AXP20X_ADC_EN1, AXP288_ADC_EN_MASK);
-}
-
static const struct iio_info axp288_adc_iio_info = {
.read_raw = &axp288_adc_read_raw,
.driver_module = THIS_MODULE,
@@ -199,7 +169,7 @@ static int axp288_adc_probe(struct platform_device *pdev)
* Set ADC to enabled state at all time, including system suspend.
* otherwise internal fuel gauge functionality may be affected.
*/
- ret = axp288_adc_set_state(axp20x->regmap);
+ ret = regmap_write(info->regmap, AXP20X_ADC_EN1, AXP288_ADC_EN_MASK);
if (ret) {
dev_err(&pdev->dev, "unable to enable ADC device\n");
return ret;
diff --git a/drivers/iio/adc/fsl-imx25-gcq.c b/drivers/iio/adc/fsl-imx25-gcq.c
index 72b32c1..ea264fa 100644
--- a/drivers/iio/adc/fsl-imx25-gcq.c
+++ b/drivers/iio/adc/fsl-imx25-gcq.c
@@ -401,6 +401,7 @@ static const struct of_device_id mx25_gcq_ids[] = {
{ .compatible = "fsl,imx25-gcq", },
{ /* Sentinel */ }
};
+MODULE_DEVICE_TABLE(of, mx25_gcq_ids);
static struct platform_driver mx25_gcq_driver = {
.driver = {
diff --git a/drivers/iio/adc/mcp320x.c b/drivers/iio/adc/mcp320x.c
index 634717a..071dd23 100644
--- a/drivers/iio/adc/mcp320x.c
+++ b/drivers/iio/adc/mcp320x.c
@@ -17,6 +17,8 @@
* MCP3204
* MCP3208
* ------------
+ * 13 bit converter
+ * MCP3301
*
* Datasheet can be found here:
* http://ww1.microchip.com/downloads/en/DeviceDoc/21293C.pdf mcp3001
@@ -96,7 +98,7 @@ static int mcp320x_channel_to_tx_data(int device_index,
}
static int mcp320x_adc_conversion(struct mcp320x *adc, u8 channel,
- bool differential, int device_index)
+ bool differential, int device_index, int *val)
{
int ret;
@@ -117,19 +119,25 @@ static int mcp320x_adc_conversion(struct mcp320x *adc, u8 channel,
switch (device_index) {
case mcp3001:
- return (adc->rx_buf[0] << 5 | adc->rx_buf[1] >> 3);
+ *val = (adc->rx_buf[0] << 5 | adc->rx_buf[1] >> 3);
+ return 0;
case mcp3002:
case mcp3004:
case mcp3008:
- return (adc->rx_buf[0] << 2 | adc->rx_buf[1] >> 6);
+ *val = (adc->rx_buf[0] << 2 | adc->rx_buf[1] >> 6);
+ return 0;
case mcp3201:
- return (adc->rx_buf[0] << 7 | adc->rx_buf[1] >> 1);
+ *val = (adc->rx_buf[0] << 7 | adc->rx_buf[1] >> 1);
+ return 0;
case mcp3202:
case mcp3204:
case mcp3208:
- return (adc->rx_buf[0] << 4 | adc->rx_buf[1] >> 4);
+ *val = (adc->rx_buf[0] << 4 | adc->rx_buf[1] >> 4);
+ return 0;
case mcp3301:
- return sign_extend32((adc->rx_buf[0] & 0x1f) << 8 | adc->rx_buf[1], 12);
+ *val = sign_extend32((adc->rx_buf[0] & 0x1f) << 8
+ | adc->rx_buf[1], 12);
+ return 0;
default:
return -EINVAL;
}
@@ -150,12 +158,10 @@ static int mcp320x_read_raw(struct iio_dev *indio_dev,
switch (mask) {
case IIO_CHAN_INFO_RAW:
ret = mcp320x_adc_conversion(adc, channel->address,
- channel->differential, device_index);
-
+ channel->differential, device_index, val);
if (ret < 0)
goto out;
- *val = ret;
ret = IIO_VAL_INT;
break;
@@ -312,6 +318,7 @@ static int mcp320x_probe(struct spi_device *spi)
indio_dev->name = spi_get_device_id(spi)->name;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->info = &mcp320x_info;
+ spi_set_drvdata(spi, indio_dev);
chip_info = &mcp320x_chip_infos[spi_get_device_id(spi)->driver_data];
indio_dev->channels = chip_info->channels;
diff --git a/drivers/iio/adc/ti-ads1015.c b/drivers/iio/adc/ti-ads1015.c
index cde6f13..472641f 100644
--- a/drivers/iio/adc/ti-ads1015.c
+++ b/drivers/iio/adc/ti-ads1015.c
@@ -80,18 +80,12 @@ static const unsigned int ads1115_data_rate[] = {
8, 16, 32, 64, 128, 250, 475, 860
};
-static const struct {
- int scale;
- int uscale;
-} ads1015_scale[] = {
- {3, 0},
- {2, 0},
- {1, 0},
- {0, 500000},
- {0, 250000},
- {0, 125000},
- {0, 125000},
- {0, 125000},
+/*
+ * Translation from PGA bits to full-scale positive and negative input voltage
+ * range in mV
+ */
+static int ads1015_fullscale_range[] = {
+ 6144, 4096, 2048, 1024, 512, 256, 256, 256
};
#define ADS1015_V_CHAN(_chan, _addr) { \
@@ -182,6 +176,12 @@ struct ads1015_data {
struct ads1015_channel_data channel_data[ADS1015_CHANNELS];
unsigned int *data_rate;
+ /*
+ * Set to true when the ADC is switched to the continuous-conversion
+ * mode and exits from a power-down state. This flag is used to avoid
+ * getting the stale result from the conversion register.
+ */
+ bool conv_invalid;
};
static bool ads1015_is_writeable_reg(struct device *dev, unsigned int reg)
@@ -234,33 +234,43 @@ static int ads1015_set_power_state(struct ads1015_data *data, bool on)
ret = pm_runtime_put_autosuspend(dev);
}
- return ret;
+ return ret < 0 ? ret : 0;
}
static
int ads1015_get_adc_result(struct ads1015_data *data, int chan, int *val)
{
int ret, pga, dr, conv_time;
- bool change;
+ unsigned int old, mask, cfg;
if (chan < 0 || chan >= ADS1015_CHANNELS)
return -EINVAL;
+ ret = regmap_read(data->regmap, ADS1015_CFG_REG, &old);
+ if (ret)
+ return ret;
+
pga = data->channel_data[chan].pga;
dr = data->channel_data[chan].data_rate;
+ mask = ADS1015_CFG_MUX_MASK | ADS1015_CFG_PGA_MASK |
+ ADS1015_CFG_DR_MASK;
+ cfg = chan << ADS1015_CFG_MUX_SHIFT | pga << ADS1015_CFG_PGA_SHIFT |
+ dr << ADS1015_CFG_DR_SHIFT;
- ret = regmap_update_bits_check(data->regmap, ADS1015_CFG_REG,
- ADS1015_CFG_MUX_MASK |
- ADS1015_CFG_PGA_MASK,
- chan << ADS1015_CFG_MUX_SHIFT |
- pga << ADS1015_CFG_PGA_SHIFT,
- &change);
- if (ret < 0)
+ cfg = (old & ~mask) | (cfg & mask);
+
+ ret = regmap_write(data->regmap, ADS1015_CFG_REG, cfg);
+ if (ret)
return ret;
- if (change) {
- conv_time = DIV_ROUND_UP(USEC_PER_SEC, data->data_rate[dr]);
+ if (old != cfg || data->conv_invalid) {
+ int dr_old = (old & ADS1015_CFG_DR_MASK) >>
+ ADS1015_CFG_DR_SHIFT;
+
+ conv_time = DIV_ROUND_UP(USEC_PER_SEC, data->data_rate[dr_old]);
+ conv_time += DIV_ROUND_UP(USEC_PER_SEC, data->data_rate[dr]);
usleep_range(conv_time, conv_time + 1);
+ data->conv_invalid = false;
}
return regmap_read(data->regmap, ADS1015_CONV_REG, val);
@@ -297,17 +307,20 @@ err:
return IRQ_HANDLED;
}
-static int ads1015_set_scale(struct ads1015_data *data, int chan,
+static int ads1015_set_scale(struct ads1015_data *data,
+ struct iio_chan_spec const *chan,
int scale, int uscale)
{
int i, ret, rindex = -1;
+ int fullscale = div_s64((scale * 1000000LL + uscale) <<
+ (chan->scan_type.realbits - 1), 1000000);
- for (i = 0; i < ARRAY_SIZE(ads1015_scale); i++)
- if (ads1015_scale[i].scale == scale &&
- ads1015_scale[i].uscale == uscale) {
+ for (i = 0; i < ARRAY_SIZE(ads1015_fullscale_range); i++) {
+ if (ads1015_fullscale_range[i] == fullscale) {
rindex = i;
break;
}
+ }
if (rindex < 0)
return -EINVAL;
@@ -317,32 +330,23 @@ static int ads1015_set_scale(struct ads1015_data *data, int chan,
if (ret < 0)
return ret;
- data->channel_data[chan].pga = rindex;
+ data->channel_data[chan->address].pga = rindex;
return 0;
}
static int ads1015_set_data_rate(struct ads1015_data *data, int chan, int rate)
{
- int i, ret, rindex = -1;
+ int i;
- for (i = 0; i < ARRAY_SIZE(ads1015_data_rate); i++)
+ for (i = 0; i < ARRAY_SIZE(ads1015_data_rate); i++) {
if (data->data_rate[i] == rate) {
- rindex = i;
- break;
+ data->channel_data[chan].data_rate = i;
+ return 0;
}
- if (rindex < 0)
- return -EINVAL;
-
- ret = regmap_update_bits(data->regmap, ADS1015_CFG_REG,
- ADS1015_CFG_DR_MASK,
- rindex << ADS1015_CFG_DR_SHIFT);
- if (ret < 0)
- return ret;
-
- data->channel_data[chan].data_rate = rindex;
+ }
- return 0;
+ return -EINVAL;
}
static int ads1015_read_raw(struct iio_dev *indio_dev,
@@ -384,9 +388,9 @@ static int ads1015_read_raw(struct iio_dev *indio_dev,
}
case IIO_CHAN_INFO_SCALE:
idx = data->channel_data[chan->address].pga;
- *val = ads1015_scale[idx].scale;
- *val2 = ads1015_scale[idx].uscale;
- ret = IIO_VAL_INT_PLUS_MICRO;
+ *val = ads1015_fullscale_range[idx];
+ *val2 = chan->scan_type.realbits - 1;
+ ret = IIO_VAL_FRACTIONAL_LOG2;
break;
case IIO_CHAN_INFO_SAMP_FREQ:
idx = data->channel_data[chan->address].data_rate;
@@ -413,7 +417,7 @@ static int ads1015_write_raw(struct iio_dev *indio_dev,
mutex_lock(&data->lock);
switch (mask) {
case IIO_CHAN_INFO_SCALE:
- ret = ads1015_set_scale(data, chan->address, val, val2);
+ ret = ads1015_set_scale(data, chan, val, val2);
break;
case IIO_CHAN_INFO_SAMP_FREQ:
ret = ads1015_set_data_rate(data, chan->address, val);
@@ -445,7 +449,10 @@ static const struct iio_buffer_setup_ops ads1015_buffer_setup_ops = {
.validate_scan_mask = &iio_validate_scan_mask_onehot,
};
-static IIO_CONST_ATTR(scale_available, "3 2 1 0.5 0.25 0.125");
+static IIO_CONST_ATTR_NAMED(ads1015_scale_available, scale_available,
+ "3 2 1 0.5 0.25 0.125");
+static IIO_CONST_ATTR_NAMED(ads1115_scale_available, scale_available,
+ "0.1875 0.125 0.0625 0.03125 0.015625 0.007813");
static IIO_CONST_ATTR_NAMED(ads1015_sampling_frequency_available,
sampling_frequency_available, "128 250 490 920 1600 2400 3300");
@@ -453,7 +460,7 @@ static IIO_CONST_ATTR_NAMED(ads1115_sampling_frequency_available,
sampling_frequency_available, "8 16 32 64 128 250 475 860");
static struct attribute *ads1015_attributes[] = {
- &iio_const_attr_scale_available.dev_attr.attr,
+ &iio_const_attr_ads1015_scale_available.dev_attr.attr,
&iio_const_attr_ads1015_sampling_frequency_available.dev_attr.attr,
NULL,
};
@@ -463,7 +470,7 @@ static const struct attribute_group ads1015_attribute_group = {
};
static struct attribute *ads1115_attributes[] = {
- &iio_const_attr_scale_available.dev_attr.attr,
+ &iio_const_attr_ads1115_scale_available.dev_attr.attr,
&iio_const_attr_ads1115_sampling_frequency_available.dev_attr.attr,
NULL,
};
@@ -624,6 +631,15 @@ static int ads1015_probe(struct i2c_client *client,
dev_err(&client->dev, "iio triggered buffer setup failed\n");
return ret;
}
+
+ ret = regmap_update_bits(data->regmap, ADS1015_CFG_REG,
+ ADS1015_CFG_MOD_MASK,
+ ADS1015_CONTINUOUS << ADS1015_CFG_MOD_SHIFT);
+ if (ret)
+ return ret;
+
+ data->conv_invalid = true;
+
ret = pm_runtime_set_active(&client->dev);
if (ret)
goto err_buffer_cleanup;
@@ -679,10 +695,15 @@ static int ads1015_runtime_resume(struct device *dev)
{
struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
struct ads1015_data *data = iio_priv(indio_dev);
+ int ret;
- return regmap_update_bits(data->regmap, ADS1015_CFG_REG,
+ ret = regmap_update_bits(data->regmap, ADS1015_CFG_REG,
ADS1015_CFG_MOD_MASK,
ADS1015_CONTINUOUS << ADS1015_CFG_MOD_SHIFT);
+ if (!ret)
+ data->conv_invalid = true;
+
+ return ret;
}
#endif
diff --git a/drivers/iio/adc/twl4030-madc.c b/drivers/iio/adc/twl4030-madc.c
index 0c74869..7ffc5db 100644
--- a/drivers/iio/adc/twl4030-madc.c
+++ b/drivers/iio/adc/twl4030-madc.c
@@ -866,8 +866,10 @@ static int twl4030_madc_probe(struct platform_device *pdev)
/* Enable 3v1 bias regulator for MADC[3:6] */
madc->usb3v1 = devm_regulator_get(madc->dev, "vusb3v1");
- if (IS_ERR(madc->usb3v1))
- return -ENODEV;
+ if (IS_ERR(madc->usb3v1)) {
+ ret = -ENODEV;
+ goto err_i2c;
+ }
ret = regulator_enable(madc->usb3v1);
if (ret)
@@ -876,11 +878,13 @@ static int twl4030_madc_probe(struct platform_device *pdev)
ret = iio_device_register(iio_dev);
if (ret) {
dev_err(&pdev->dev, "could not register iio device\n");
- goto err_i2c;
+ goto err_usb3v1;
}
return 0;
+err_usb3v1:
+ regulator_disable(madc->usb3v1);
err_i2c:
twl4030_madc_set_current_generator(madc, 0, 0);
err_current_generator:
diff --git a/drivers/iio/adc/vf610_adc.c b/drivers/iio/adc/vf610_adc.c
index 228a003..d1bde6d 100644
--- a/drivers/iio/adc/vf610_adc.c
+++ b/drivers/iio/adc/vf610_adc.c
@@ -77,7 +77,7 @@
#define VF610_ADC_ADSTS_MASK 0x300
#define VF610_ADC_ADLPC_EN 0x80
#define VF610_ADC_ADHSC_EN 0x400
-#define VF610_ADC_REFSEL_VALT 0x100
+#define VF610_ADC_REFSEL_VALT 0x800
#define VF610_ADC_REFSEL_VBG 0x1000
#define VF610_ADC_ADTRG_HARD 0x2000
#define VF610_ADC_AVGS_8 0x4000
diff --git a/drivers/iio/adc/xilinx-xadc-core.c b/drivers/iio/adc/xilinx-xadc-core.c
index 0a6beb3..56cf590 100644
--- a/drivers/iio/adc/xilinx-xadc-core.c
+++ b/drivers/iio/adc/xilinx-xadc-core.c
@@ -1208,7 +1208,7 @@ static int xadc_probe(struct platform_device *pdev)
ret = xadc->ops->setup(pdev, indio_dev, irq);
if (ret)
- goto err_free_samplerate_trigger;
+ goto err_clk_disable_unprepare;
ret = request_irq(irq, xadc->ops->interrupt_handler, 0,
dev_name(&pdev->dev), indio_dev);
@@ -1268,6 +1268,8 @@ static int xadc_probe(struct platform_device *pdev)
err_free_irq:
free_irq(irq, indio_dev);
+err_clk_disable_unprepare:
+ clk_disable_unprepare(xadc->clk);
err_free_samplerate_trigger:
if (xadc->ops->flags & XADC_FLAGS_BUFFERED)
iio_trigger_free(xadc->samplerate_trigger);
@@ -1277,8 +1279,6 @@ err_free_convst_trigger:
err_triggered_buffer_cleanup:
if (xadc->ops->flags & XADC_FLAGS_BUFFERED)
iio_triggered_buffer_cleanup(indio_dev);
-err_clk_disable_unprepare:
- clk_disable_unprepare(xadc->clk);
err_device_free:
kfree(indio_dev->channels);