Commit 92f0afb5 authored by Matt Ranostay's avatar Matt Ranostay Committed by Jonathan Cameron

iio: adc: ti-adc161s626: add regulator support

Allow IIO_CHAN_INFO_SCALE and IIO_CHAN_INFO_OFFSET attributes for
processing by checking voltage from a regulator.
Signed-off-by: default avatarMatt Ranostay <matt@ranostay.consulting>
Signed-off-by: default avatarJonathan Cameron <jic23@kernel.org>
parent 0023e67d
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
Required properties: Required properties:
- compatible: Should be "ti,adc141s626" or "ti,adc161s626" - compatible: Should be "ti,adc141s626" or "ti,adc161s626"
- reg: spi chip select number for the device - reg: spi chip select number for the device
- vdda-supply: supply voltage to VDDA pin
Recommended properties: Recommended properties:
- spi-max-frequency: Definition as per - spi-max-frequency: Definition as per
...@@ -11,6 +12,7 @@ Recommended properties: ...@@ -11,6 +12,7 @@ Recommended properties:
Example: Example:
adc@0 { adc@0 {
compatible = "ti,adc161s626"; compatible = "ti,adc161s626";
vdda-supply = <&vdda_fixed>;
reg = <0>; reg = <0>;
spi-max-frequency = <4300000>; spi-max-frequency = <4300000>;
}; };
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include <linux/iio/buffer.h> #include <linux/iio/buffer.h>
#include <linux/iio/trigger_consumer.h> #include <linux/iio/trigger_consumer.h>
#include <linux/iio/triggered_buffer.h> #include <linux/iio/triggered_buffer.h>
#include <linux/regulator/consumer.h>
#define TI_ADC_DRV_NAME "ti-adc161s626" #define TI_ADC_DRV_NAME "ti-adc161s626"
...@@ -39,7 +40,9 @@ static const struct iio_chan_spec ti_adc141s626_channels[] = { ...@@ -39,7 +40,9 @@ static const struct iio_chan_spec ti_adc141s626_channels[] = {
{ {
.type = IIO_VOLTAGE, .type = IIO_VOLTAGE,
.channel = 0, .channel = 0,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
BIT(IIO_CHAN_INFO_SCALE) |
BIT(IIO_CHAN_INFO_OFFSET),
.scan_index = 0, .scan_index = 0,
.scan_type = { .scan_type = {
.sign = 's', .sign = 's',
...@@ -54,7 +57,9 @@ static const struct iio_chan_spec ti_adc161s626_channels[] = { ...@@ -54,7 +57,9 @@ static const struct iio_chan_spec ti_adc161s626_channels[] = {
{ {
.type = IIO_VOLTAGE, .type = IIO_VOLTAGE,
.channel = 0, .channel = 0,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
BIT(IIO_CHAN_INFO_SCALE) |
BIT(IIO_CHAN_INFO_OFFSET),
.scan_index = 0, .scan_index = 0,
.scan_type = { .scan_type = {
.sign = 's', .sign = 's',
...@@ -68,6 +73,8 @@ static const struct iio_chan_spec ti_adc161s626_channels[] = { ...@@ -68,6 +73,8 @@ static const struct iio_chan_spec ti_adc161s626_channels[] = {
struct ti_adc_data { struct ti_adc_data {
struct iio_dev *indio_dev; struct iio_dev *indio_dev;
struct spi_device *spi; struct spi_device *spi;
struct regulator *ref;
u8 read_size; u8 read_size;
u8 shift; u8 shift;
...@@ -135,18 +142,32 @@ static int ti_adc_read_raw(struct iio_dev *indio_dev, ...@@ -135,18 +142,32 @@ static int ti_adc_read_raw(struct iio_dev *indio_dev,
struct ti_adc_data *data = iio_priv(indio_dev); struct ti_adc_data *data = iio_priv(indio_dev);
int ret; int ret;
if (mask != IIO_CHAN_INFO_RAW) switch (mask) {
return -EINVAL; case IIO_CHAN_INFO_RAW:
ret = iio_device_claim_direct_mode(indio_dev);
if (ret)
return ret;
ret = iio_device_claim_direct_mode(indio_dev); ret = ti_adc_read_measurement(data, chan, val);
if (ret) iio_device_release_direct_mode(indio_dev);
return ret;
ret = ti_adc_read_measurement(data, chan, val); if (ret)
iio_device_release_direct_mode(indio_dev); return ret;
if (!ret)
return IIO_VAL_INT; return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
ret = regulator_get_voltage(data->ref);
if (ret < 0)
return ret;
*val = ret / 1000;
*val2 = chan->scan_type.realbits;
return IIO_VAL_FRACTIONAL_LOG2;
case IIO_CHAN_INFO_OFFSET:
*val = 1 << (chan->scan_type.realbits - 1);
return IIO_VAL_INT;
}
return 0; return 0;
} }
...@@ -191,10 +212,17 @@ static int ti_adc_probe(struct spi_device *spi) ...@@ -191,10 +212,17 @@ static int ti_adc_probe(struct spi_device *spi)
break; break;
} }
data->ref = devm_regulator_get(&spi->dev, "vdda");
if (!IS_ERR(data->ref)) {
ret = regulator_enable(data->ref);
if (ret < 0)
return ret;
}
ret = iio_triggered_buffer_setup(indio_dev, NULL, ret = iio_triggered_buffer_setup(indio_dev, NULL,
ti_adc_trigger_handler, NULL); ti_adc_trigger_handler, NULL);
if (ret) if (ret)
return ret; goto error_regulator_disable;
ret = iio_device_register(indio_dev); ret = iio_device_register(indio_dev);
if (ret) if (ret)
...@@ -205,15 +233,20 @@ static int ti_adc_probe(struct spi_device *spi) ...@@ -205,15 +233,20 @@ static int ti_adc_probe(struct spi_device *spi)
error_unreg_buffer: error_unreg_buffer:
iio_triggered_buffer_cleanup(indio_dev); iio_triggered_buffer_cleanup(indio_dev);
error_regulator_disable:
regulator_disable(data->ref);
return ret; return ret;
} }
static int ti_adc_remove(struct spi_device *spi) static int ti_adc_remove(struct spi_device *spi)
{ {
struct iio_dev *indio_dev = spi_get_drvdata(spi); struct iio_dev *indio_dev = spi_get_drvdata(spi);
struct ti_adc_data *data = iio_priv(indio_dev);
iio_device_unregister(indio_dev); iio_device_unregister(indio_dev);
iio_triggered_buffer_cleanup(indio_dev); iio_triggered_buffer_cleanup(indio_dev);
regulator_disable(data->ref);
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment