* [PATCH 01/22] staging:iio:ad7793: Add missing break in switch statement
@ 2012-08-10 16:36 Lars-Peter Clausen
2012-08-10 16:36 ` [PATCH 02/22] staging:iio:ad7793: Mark channels as unsigned Lars-Peter Clausen
` (20 more replies)
0 siblings, 21 replies; 37+ messages in thread
From: Lars-Peter Clausen @ 2012-08-10 16:36 UTC (permalink / raw)
To: Jonathan Cameron; +Cc: linux-iio, drivers, Lars-Peter Clausen
Without the break statement we fall right through to the default case and return
an error value.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
---
drivers/staging/iio/adc/ad7793.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/staging/iio/adc/ad7793.c b/drivers/staging/iio/adc/ad7793.c
index 76fdd71..1d0cd09 100644
--- a/drivers/staging/iio/adc/ad7793.c
+++ b/drivers/staging/iio/adc/ad7793.c
@@ -676,7 +676,7 @@ static int ad7793_write_raw(struct iio_dev *indio_dev,
}
ret = 0;
}
-
+ break;
default:
ret = -EINVAL;
}
--
1.7.10.4
^ permalink raw reply related [flat|nested] 37+ messages in thread
* [PATCH 02/22] staging:iio:ad7793: Mark channels as unsigned
2012-08-10 16:36 [PATCH 01/22] staging:iio:ad7793: Add missing break in switch statement Lars-Peter Clausen
@ 2012-08-10 16:36 ` Lars-Peter Clausen
2012-08-10 16:36 ` [PATCH 03/22] staging:iio:ad7793: Report channel offset Lars-Peter Clausen
` (19 subsequent siblings)
20 siblings, 0 replies; 37+ messages in thread
From: Lars-Peter Clausen @ 2012-08-10 16:36 UTC (permalink / raw)
To: Jonathan Cameron; +Cc: linux-iio, drivers, Lars-Peter Clausen
The values reported by the AD7793 are unsigned.
In uniploar mode:
0x000000 is zeroscale
0xffffff is fullscale
In bipolar mode:
0x000000 is negative fullscale
0x800000 is zeroscale
0xffffff is positive fullscale
In bipolar mode there is a binary offset, but the values are still unsigned.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
---
drivers/staging/iio/adc/ad7793.c | 24 ++++++++++++------------
1 file changed, 12 insertions(+), 12 deletions(-)
diff --git a/drivers/staging/iio/adc/ad7793.c b/drivers/staging/iio/adc/ad7793.c
index 1d0cd09..5e457a4 100644
--- a/drivers/staging/iio/adc/ad7793.c
+++ b/drivers/staging/iio/adc/ad7793.c
@@ -722,7 +722,7 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = {
.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SHARED_BIT,
.scan_index = 0,
- .scan_type = IIO_ST('s', 24, 32, 0)
+ .scan_type = IIO_ST('u', 24, 32, 0)
},
.channel[1] = {
.type = IIO_VOLTAGE,
@@ -734,7 +734,7 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = {
.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SHARED_BIT,
.scan_index = 1,
- .scan_type = IIO_ST('s', 24, 32, 0)
+ .scan_type = IIO_ST('u', 24, 32, 0)
},
.channel[2] = {
.type = IIO_VOLTAGE,
@@ -746,7 +746,7 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = {
.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SHARED_BIT,
.scan_index = 2,
- .scan_type = IIO_ST('s', 24, 32, 0)
+ .scan_type = IIO_ST('u', 24, 32, 0)
},
.channel[3] = {
.type = IIO_VOLTAGE,
@@ -759,7 +759,7 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = {
.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SHARED_BIT,
.scan_index = 3,
- .scan_type = IIO_ST('s', 24, 32, 0)
+ .scan_type = IIO_ST('u', 24, 32, 0)
},
.channel[4] = {
.type = IIO_TEMP,
@@ -769,7 +769,7 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = {
.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
.scan_index = 4,
- .scan_type = IIO_ST('s', 24, 32, 0),
+ .scan_type = IIO_ST('u', 24, 32, 0),
},
.channel[5] = {
.type = IIO_VOLTAGE,
@@ -780,7 +780,7 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = {
.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
.scan_index = 5,
- .scan_type = IIO_ST('s', 24, 32, 0),
+ .scan_type = IIO_ST('u', 24, 32, 0),
},
.channel[6] = IIO_CHAN_SOFT_TIMESTAMP(6),
},
@@ -795,7 +795,7 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = {
.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SHARED_BIT,
.scan_index = 0,
- .scan_type = IIO_ST('s', 16, 32, 0)
+ .scan_type = IIO_ST('u', 16, 32, 0)
},
.channel[1] = {
.type = IIO_VOLTAGE,
@@ -807,7 +807,7 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = {
.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SHARED_BIT,
.scan_index = 1,
- .scan_type = IIO_ST('s', 16, 32, 0)
+ .scan_type = IIO_ST('u', 16, 32, 0)
},
.channel[2] = {
.type = IIO_VOLTAGE,
@@ -819,7 +819,7 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = {
.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SHARED_BIT,
.scan_index = 2,
- .scan_type = IIO_ST('s', 16, 32, 0)
+ .scan_type = IIO_ST('u', 16, 32, 0)
},
.channel[3] = {
.type = IIO_VOLTAGE,
@@ -832,7 +832,7 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = {
.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SHARED_BIT,
.scan_index = 3,
- .scan_type = IIO_ST('s', 16, 32, 0)
+ .scan_type = IIO_ST('u', 16, 32, 0)
},
.channel[4] = {
.type = IIO_TEMP,
@@ -842,7 +842,7 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = {
.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
.scan_index = 4,
- .scan_type = IIO_ST('s', 16, 32, 0),
+ .scan_type = IIO_ST('u', 16, 32, 0),
},
.channel[5] = {
.type = IIO_VOLTAGE,
@@ -853,7 +853,7 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = {
.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
.scan_index = 5,
- .scan_type = IIO_ST('s', 16, 32, 0),
+ .scan_type = IIO_ST('u', 16, 32, 0),
},
.channel[6] = IIO_CHAN_SOFT_TIMESTAMP(6),
},
--
1.7.10.4
^ permalink raw reply related [flat|nested] 37+ messages in thread
* [PATCH 03/22] staging:iio:ad7793: Report channel offset
2012-08-10 16:36 [PATCH 01/22] staging:iio:ad7793: Add missing break in switch statement Lars-Peter Clausen
2012-08-10 16:36 ` [PATCH 02/22] staging:iio:ad7793: Mark channels as unsigned Lars-Peter Clausen
@ 2012-08-10 16:36 ` Lars-Peter Clausen
2012-08-10 16:36 ` [PATCH 04/22] staging:iio:ad7793: Fix temperature scale and offset Lars-Peter Clausen
` (18 subsequent siblings)
20 siblings, 0 replies; 37+ messages in thread
From: Lars-Peter Clausen @ 2012-08-10 16:36 UTC (permalink / raw)
To: Jonathan Cameron; +Cc: linux-iio, drivers, Lars-Peter Clausen
In bipolar mode there is a a binary offset of 2**(N-1) (with N being the number
of bits) on the reported value. Currently this value is subtracted when doing a
manual read. While this works for manual channel readings it does not work for
buffered mode. So report the offset in the channels offset property, which will
work in both modes.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
---
drivers/staging/iio/adc/ad7793.c | 39 +++++++++++++++++++++++++-------------
1 file changed, 26 insertions(+), 13 deletions(-)
diff --git a/drivers/staging/iio/adc/ad7793.c b/drivers/staging/iio/adc/ad7793.c
index 5e457a4..56014a8 100644
--- a/drivers/staging/iio/adc/ad7793.c
+++ b/drivers/staging/iio/adc/ad7793.c
@@ -604,9 +604,6 @@ static int ad7793_read_raw(struct iio_dev *indio_dev,
*val = (smpl >> chan->scan_type.shift) &
((1 << (chan->scan_type.realbits)) - 1);
- if (!unipolar)
- *val -= (1 << (chan->scan_type.realbits - 1));
-
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
@@ -639,6 +636,12 @@ static int ad7793_read_raw(struct iio_dev *indio_dev,
*val = scale_uv;
return IIO_VAL_INT_PLUS_NANO;
+ case IIO_CHAN_INFO_OFFSET:
+ if (!unipolar)
+ *val -= (1 << (chan->scan_type.realbits - 1));
+ else
+ *val = 0;
+ return IIO_VAL_INT;
}
return -EINVAL;
}
@@ -720,7 +723,8 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = {
.channel2 = 0,
.address = AD7793_CH_AIN1P_AIN1M,
.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
- IIO_CHAN_INFO_SCALE_SHARED_BIT,
+ IIO_CHAN_INFO_SCALE_SHARED_BIT |
+ IIO_CHAN_INFO_OFFSET_SHARED_BIT,
.scan_index = 0,
.scan_type = IIO_ST('u', 24, 32, 0)
},
@@ -732,7 +736,8 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = {
.channel2 = 1,
.address = AD7793_CH_AIN2P_AIN2M,
.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
- IIO_CHAN_INFO_SCALE_SHARED_BIT,
+ IIO_CHAN_INFO_SCALE_SHARED_BIT |
+ IIO_CHAN_INFO_OFFSET_SHARED_BIT,
.scan_index = 1,
.scan_type = IIO_ST('u', 24, 32, 0)
},
@@ -744,7 +749,8 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = {
.channel2 = 2,
.address = AD7793_CH_AIN3P_AIN3M,
.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
- IIO_CHAN_INFO_SCALE_SHARED_BIT,
+ IIO_CHAN_INFO_SCALE_SHARED_BIT |
+ IIO_CHAN_INFO_OFFSET_SHARED_BIT,
.scan_index = 2,
.scan_type = IIO_ST('u', 24, 32, 0)
},
@@ -757,7 +763,8 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = {
.channel2 = 2,
.address = AD7793_CH_AIN1M_AIN1M,
.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
- IIO_CHAN_INFO_SCALE_SHARED_BIT,
+ IIO_CHAN_INFO_SCALE_SHARED_BIT |
+ IIO_CHAN_INFO_OFFSET_SHARED_BIT,
.scan_index = 3,
.scan_type = IIO_ST('u', 24, 32, 0)
},
@@ -778,7 +785,8 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = {
.channel = 4,
.address = AD7793_CH_AVDD_MONITOR,
.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
- IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT |
+ IIO_CHAN_INFO_OFFSET_SHARED_BIT,
.scan_index = 5,
.scan_type = IIO_ST('u', 24, 32, 0),
},
@@ -793,7 +801,8 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = {
.channel2 = 0,
.address = AD7793_CH_AIN1P_AIN1M,
.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
- IIO_CHAN_INFO_SCALE_SHARED_BIT,
+ IIO_CHAN_INFO_SCALE_SHARED_BIT |
+ IIO_CHAN_INFO_OFFSET_SHARED_BIT,
.scan_index = 0,
.scan_type = IIO_ST('u', 16, 32, 0)
},
@@ -805,7 +814,8 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = {
.channel2 = 1,
.address = AD7793_CH_AIN2P_AIN2M,
.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
- IIO_CHAN_INFO_SCALE_SHARED_BIT,
+ IIO_CHAN_INFO_SCALE_SHARED_BIT |
+ IIO_CHAN_INFO_OFFSET_SHARED_BIT,
.scan_index = 1,
.scan_type = IIO_ST('u', 16, 32, 0)
},
@@ -817,7 +827,8 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = {
.channel2 = 2,
.address = AD7793_CH_AIN3P_AIN3M,
.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
- IIO_CHAN_INFO_SCALE_SHARED_BIT,
+ IIO_CHAN_INFO_SCALE_SHARED_BIT |
+ IIO_CHAN_INFO_OFFSET_SHARED_BIT,
.scan_index = 2,
.scan_type = IIO_ST('u', 16, 32, 0)
},
@@ -830,7 +841,8 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = {
.channel2 = 2,
.address = AD7793_CH_AIN1M_AIN1M,
.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
- IIO_CHAN_INFO_SCALE_SHARED_BIT,
+ IIO_CHAN_INFO_SCALE_SHARED_BIT |
+ IIO_CHAN_INFO_OFFSET_SHARED_BIT,
.scan_index = 3,
.scan_type = IIO_ST('u', 16, 32, 0)
},
@@ -851,7 +863,8 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = {
.channel = 4,
.address = AD7793_CH_AVDD_MONITOR,
.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
- IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
+ IIO_CHAN_INFO_SCALE_SEPARATE_BIT |
+ IIO_CHAN_INFO_OFFSET_SHARED_BIT,
.scan_index = 5,
.scan_type = IIO_ST('u', 16, 32, 0),
},
--
1.7.10.4
^ permalink raw reply related [flat|nested] 37+ messages in thread
* [PATCH 04/22] staging:iio:ad7793: Fix temperature scale and offset
2012-08-10 16:36 [PATCH 01/22] staging:iio:ad7793: Add missing break in switch statement Lars-Peter Clausen
2012-08-10 16:36 ` [PATCH 02/22] staging:iio:ad7793: Mark channels as unsigned Lars-Peter Clausen
2012-08-10 16:36 ` [PATCH 03/22] staging:iio:ad7793: Report channel offset Lars-Peter Clausen
@ 2012-08-10 16:36 ` Lars-Peter Clausen
2012-08-10 16:36 ` [PATCH 05/22] staging:iio:ad7793: Follow new IIO naming spec Lars-Peter Clausen
` (17 subsequent siblings)
20 siblings, 0 replies; 37+ messages in thread
From: Lars-Peter Clausen @ 2012-08-10 16:36 UTC (permalink / raw)
To: Jonathan Cameron; +Cc: linux-iio, drivers, Lars-Peter Clausen
The temperature channel uses the internal 1.17V reference with 0.81 mv/C. The
reported temperature is in Kevlin, so we need to add the Kelvin to Celcius
offset when reporting the offset for the temperature channel.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
---
drivers/staging/iio/adc/ad7793.c | 29 ++++++++++++++++++-----------
1 file changed, 18 insertions(+), 11 deletions(-)
diff --git a/drivers/staging/iio/adc/ad7793.c b/drivers/staging/iio/adc/ad7793.c
index 56014a8..3c8d1d4 100644
--- a/drivers/staging/iio/adc/ad7793.c
+++ b/drivers/staging/iio/adc/ad7793.c
@@ -617,30 +617,37 @@ static int ad7793_read_raw(struct iio_dev *indio_dev,
return IIO_VAL_INT_PLUS_NANO;
} else {
/* 1170mV / 2^23 * 6 */
- scale_uv = (1170ULL * 100000000ULL * 6ULL)
- >> (chan->scan_type.realbits -
- (unipolar ? 0 : 1));
+ scale_uv = (1170ULL * 100000000ULL * 6ULL);
}
break;
case IIO_TEMP:
- /* Always uses unity gain and internal ref */
- scale_uv = (2500ULL * 100000000ULL)
- >> (chan->scan_type.realbits -
- (unipolar ? 0 : 1));
+ /* 1170mV / 0.81 mV/C / 2^23 */
+ scale_uv = 1444444444444ULL;
break;
default:
return -EINVAL;
}
- *val2 = do_div(scale_uv, 100000000) * 10;
- *val = scale_uv;
-
+ scale_uv >>= (chan->scan_type.realbits - (unipolar ? 0 : 1));
+ *val = 0;
+ *val2 = scale_uv;
return IIO_VAL_INT_PLUS_NANO;
case IIO_CHAN_INFO_OFFSET:
if (!unipolar)
- *val -= (1 << (chan->scan_type.realbits - 1));
+ *val = -(1 << (chan->scan_type.realbits - 1));
else
*val = 0;
+
+ /* Kelvin to Celsius */
+ if (chan->type == IIO_TEMP) {
+ unsigned long long offset;
+ unsigned int shift;
+
+ shift = chan->scan_type.realbits - (unipolar ? 0 : 1);
+ offset = 273ULL << shift;
+ do_div(offset, 1444);
+ *val -= offset;
+ }
return IIO_VAL_INT;
}
return -EINVAL;
--
1.7.10.4
^ permalink raw reply related [flat|nested] 37+ messages in thread
* [PATCH 05/22] staging:iio:ad7793: Follow new IIO naming spec
2012-08-10 16:36 [PATCH 01/22] staging:iio:ad7793: Add missing break in switch statement Lars-Peter Clausen
` (2 preceding siblings ...)
2012-08-10 16:36 ` [PATCH 04/22] staging:iio:ad7793: Fix temperature scale and offset Lars-Peter Clausen
@ 2012-08-10 16:36 ` Lars-Peter Clausen
2012-08-10 16:36 ` [PATCH 06/22] staging:iio:ad7793: Fix internal reference value Lars-Peter Clausen
` (16 subsequent siblings)
20 siblings, 0 replies; 37+ messages in thread
From: Lars-Peter Clausen @ 2012-08-10 16:36 UTC (permalink / raw)
To: Jonathan Cameron; +Cc: linux-iio, drivers, Lars-Peter Clausen
Make the "in-in_scale_available" attribute follow the new naming spec and
rename it to "in_voltage-voltage_scale_available".
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
---
drivers/staging/iio/adc/ad7793.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/staging/iio/adc/ad7793.c b/drivers/staging/iio/adc/ad7793.c
index 3c8d1d4..91cb95c 100644
--- a/drivers/staging/iio/adc/ad7793.c
+++ b/drivers/staging/iio/adc/ad7793.c
@@ -563,8 +563,9 @@ static ssize_t ad7793_show_scale_available(struct device *dev,
return len;
}
-static IIO_DEVICE_ATTR_NAMED(in_m_in_scale_available, in-in_scale_available,
- S_IRUGO, ad7793_show_scale_available, NULL, 0);
+static IIO_DEVICE_ATTR_NAMED(in_m_in_scale_available,
+ in_voltage-voltage_scale_available, S_IRUGO,
+ ad7793_show_scale_available, NULL, 0);
static struct attribute *ad7793_attributes[] = {
&iio_dev_attr_sampling_frequency.dev_attr.attr,
--
1.7.10.4
^ permalink raw reply related [flat|nested] 37+ messages in thread
* [PATCH 06/22] staging:iio:ad7793: Fix internal reference value
2012-08-10 16:36 [PATCH 01/22] staging:iio:ad7793: Add missing break in switch statement Lars-Peter Clausen
` (3 preceding siblings ...)
2012-08-10 16:36 ` [PATCH 05/22] staging:iio:ad7793: Follow new IIO naming spec Lars-Peter Clausen
@ 2012-08-10 16:36 ` Lars-Peter Clausen
2012-08-10 16:36 ` [PATCH 07/22] staging:iio:ad7793: Remove unused platform_data from device state struct Lars-Peter Clausen
` (15 subsequent siblings)
20 siblings, 0 replies; 37+ messages in thread
From: Lars-Peter Clausen @ 2012-08-10 16:36 UTC (permalink / raw)
To: Jonathan Cameron; +Cc: linux-iio, drivers, Lars-Peter Clausen
The internal reference for the ad7793 and similar is 1.17V
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
---
drivers/staging/iio/adc/ad7793.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/staging/iio/adc/ad7793.c b/drivers/staging/iio/adc/ad7793.c
index 91cb95c..112e2b7 100644
--- a/drivers/staging/iio/adc/ad7793.c
+++ b/drivers/staging/iio/adc/ad7793.c
@@ -922,7 +922,7 @@ static int __devinit ad7793_probe(struct spi_device *spi)
else if (voltage_uv)
st->int_vref_mv = voltage_uv / 1000;
else
- st->int_vref_mv = 2500; /* Build-in ref */
+ st->int_vref_mv = 1170; /* Build-in ref */
spi_set_drvdata(spi, indio_dev);
st->spi = spi;
--
1.7.10.4
^ permalink raw reply related [flat|nested] 37+ messages in thread
* [PATCH 07/22] staging:iio:ad7793: Remove unused platform_data from device state struct
2012-08-10 16:36 [PATCH 01/22] staging:iio:ad7793: Add missing break in switch statement Lars-Peter Clausen
` (4 preceding siblings ...)
2012-08-10 16:36 ` [PATCH 06/22] staging:iio:ad7793: Fix internal reference value Lars-Peter Clausen
@ 2012-08-10 16:36 ` Lars-Peter Clausen
2012-08-14 19:39 ` Jonathan Cameron
2012-08-10 16:36 ` [PATCH 08/22] staging:iio:ad7192: Add missing break in switch statement Lars-Peter Clausen
` (14 subsequent siblings)
20 siblings, 1 reply; 37+ messages in thread
From: Lars-Peter Clausen @ 2012-08-10 16:36 UTC (permalink / raw)
To: Jonathan Cameron; +Cc: linux-iio, drivers, Lars-Peter Clausen
The platform data for the device is only used from within the drivers probe
callback, so there is no need to keep it around in the devices state struct.
While we are at it mark the platform data struct as const.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
---
drivers/staging/iio/adc/ad7793.c | 14 ++++++--------
1 file changed, 6 insertions(+), 8 deletions(-)
diff --git a/drivers/staging/iio/adc/ad7793.c b/drivers/staging/iio/adc/ad7793.c
index 112e2b7..0ba598e 100644
--- a/drivers/staging/iio/adc/ad7793.c
+++ b/drivers/staging/iio/adc/ad7793.c
@@ -44,7 +44,6 @@ struct ad7793_state {
struct iio_trigger *trig;
const struct ad7793_chip_info *chip_info;
struct regulator *reg;
- struct ad7793_platform_data *pdata;
wait_queue_head_t wq_data_avail;
bool done;
bool irq_dis;
@@ -253,7 +252,8 @@ out:
return ret;
}
-static int ad7793_setup(struct ad7793_state *st)
+static int ad7793_setup(struct ad7793_state *st
+ const struct ad7793_platform_data *pdata)
{
int i, ret = -1;
unsigned long long scale_uv;
@@ -277,9 +277,9 @@ static int ad7793_setup(struct ad7793_state *st)
goto out;
}
- st->mode = (st->pdata->mode & ~AD7793_MODE_SEL(-1)) |
+ st->mode = (pdata->mode & ~AD7793_MODE_SEL(-1)) |
AD7793_MODE_SEL(AD7793_MODE_IDLE);
- st->conf = st->pdata->conf & ~AD7793_CONF_CHAN(-1);
+ st->conf = pdata->conf & ~AD7793_CONF_CHAN(-1);
ret = ad7793_write_reg(st, AD7793_REG_MODE, sizeof(st->mode), st->mode);
if (ret)
@@ -882,7 +882,7 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = {
static int __devinit ad7793_probe(struct spi_device *spi)
{
- struct ad7793_platform_data *pdata = spi->dev.platform_data;
+ const struct ad7793_platform_data *pdata = spi->dev.platform_data;
struct ad7793_state *st;
struct iio_dev *indio_dev;
int ret, voltage_uv = 0;
@@ -915,8 +915,6 @@ static int __devinit ad7793_probe(struct spi_device *spi)
st->chip_info =
&ad7793_chip_info_tbl[spi_get_device_id(spi)->driver_data];
- st->pdata = pdata;
-
if (pdata && pdata->vref_mv)
st->int_vref_mv = pdata->vref_mv;
else if (voltage_uv)
@@ -944,7 +942,7 @@ static int __devinit ad7793_probe(struct spi_device *spi)
if (ret)
goto error_unreg_ring;
- ret = ad7793_setup(st);
+ ret = ad7793_setup(st, pdata);
if (ret)
goto error_remove_trigger;
--
1.7.10.4
^ permalink raw reply related [flat|nested] 37+ messages in thread
* [PATCH 08/22] staging:iio:ad7192: Add missing break in switch statement
2012-08-10 16:36 [PATCH 01/22] staging:iio:ad7793: Add missing break in switch statement Lars-Peter Clausen
` (5 preceding siblings ...)
2012-08-10 16:36 ` [PATCH 07/22] staging:iio:ad7793: Remove unused platform_data from device state struct Lars-Peter Clausen
@ 2012-08-10 16:36 ` Lars-Peter Clausen
2012-08-10 16:36 ` [PATCH 09/22] staging:iio:ad7192: Fix setting ACX Lars-Peter Clausen
` (13 subsequent siblings)
20 siblings, 0 replies; 37+ messages in thread
From: Lars-Peter Clausen @ 2012-08-10 16:36 UTC (permalink / raw)
To: Jonathan Cameron; +Cc: linux-iio, drivers, Lars-Peter Clausen
Without the break statement we fall right through to the default case and return
an error value.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
---
drivers/staging/iio/adc/ad7192.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/staging/iio/adc/ad7192.c b/drivers/staging/iio/adc/ad7192.c
index e381d4b..d65feda 100644
--- a/drivers/staging/iio/adc/ad7192.c
+++ b/drivers/staging/iio/adc/ad7192.c
@@ -890,7 +890,7 @@ static int ad7192_write_raw(struct iio_dev *indio_dev,
}
ret = 0;
}
-
+ break;
default:
ret = -EINVAL;
}
--
1.7.10.4
^ permalink raw reply related [flat|nested] 37+ messages in thread
* [PATCH 09/22] staging:iio:ad7192: Fix setting ACX
2012-08-10 16:36 [PATCH 01/22] staging:iio:ad7793: Add missing break in switch statement Lars-Peter Clausen
` (6 preceding siblings ...)
2012-08-10 16:36 ` [PATCH 08/22] staging:iio:ad7192: Add missing break in switch statement Lars-Peter Clausen
@ 2012-08-10 16:36 ` Lars-Peter Clausen
2012-08-10 16:36 ` [PATCH 10/22] staging:iio:ad7192: Mark channels as unsigned Lars-Peter Clausen
` (12 subsequent siblings)
20 siblings, 0 replies; 37+ messages in thread
From: Lars-Peter Clausen @ 2012-08-10 16:36 UTC (permalink / raw)
To: Jonathan Cameron; +Cc: linux-iio, drivers, Lars-Peter Clausen
Write to the correct register when setting the ACX bit.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
---
drivers/staging/iio/adc/ad7192.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/staging/iio/adc/ad7192.c b/drivers/staging/iio/adc/ad7192.c
index d65feda..5565268 100644
--- a/drivers/staging/iio/adc/ad7192.c
+++ b/drivers/staging/iio/adc/ad7192.c
@@ -754,7 +754,7 @@ static ssize_t ad7192_set(struct device *dev,
else
st->mode &= ~AD7192_MODE_ACX;
- ad7192_write_reg(st, AD7192_REG_GPOCON, 3, st->mode);
+ ad7192_write_reg(st, AD7192_REG_MODE, 3, st->mode);
break;
default:
ret = -EINVAL;
--
1.7.10.4
^ permalink raw reply related [flat|nested] 37+ messages in thread
* [PATCH 10/22] staging:iio:ad7192: Mark channels as unsigned
2012-08-10 16:36 [PATCH 01/22] staging:iio:ad7793: Add missing break in switch statement Lars-Peter Clausen
` (7 preceding siblings ...)
2012-08-10 16:36 ` [PATCH 09/22] staging:iio:ad7192: Fix setting ACX Lars-Peter Clausen
@ 2012-08-10 16:36 ` Lars-Peter Clausen
2012-08-10 16:36 ` [PATCH 11/22] staging:iio:ad7192: Report channel offset Lars-Peter Clausen
` (11 subsequent siblings)
20 siblings, 0 replies; 37+ messages in thread
From: Lars-Peter Clausen @ 2012-08-10 16:36 UTC (permalink / raw)
To: Jonathan Cameron; +Cc: linux-iio, drivers, Lars-Peter Clausen
The values reported by the AD7793 are unsigned.
In uniploar mode:
0x000000 is zeroscale
0xffffff is fullscale
In bipolar mode:
0x000000 is negative fullscale
0x800000 is zeroscale
0xffffff is positive fullscale
In bipolar mode there is a binary offset, but the values are still unsigned.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
---
drivers/staging/iio/adc/ad7192.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/staging/iio/adc/ad7192.c b/drivers/staging/iio/adc/ad7192.c
index 5565268..b103f58 100644
--- a/drivers/staging/iio/adc/ad7192.c
+++ b/drivers/staging/iio/adc/ad7192.c
@@ -945,7 +945,7 @@ static const struct iio_info ad7195_info = {
IIO_CHAN_INFO_SCALE_SHARED_BIT, \
.address = _address, \
.scan_index = _si, \
- .scan_type = IIO_ST('s', 24, 32, 0)}
+ .scan_type = IIO_ST('u', 24, 32, 0)}
#define AD7192_CHAN(_chan, _address, _si) \
{ .type = IIO_VOLTAGE, \
@@ -955,7 +955,7 @@ static const struct iio_info ad7195_info = {
IIO_CHAN_INFO_SCALE_SHARED_BIT, \
.address = _address, \
.scan_index = _si, \
- .scan_type = IIO_ST('s', 24, 32, 0)}
+ .scan_type = IIO_ST('u', 24, 32, 0)}
#define AD7192_CHAN_TEMP(_chan, _address, _si) \
{ .type = IIO_TEMP, \
@@ -965,7 +965,7 @@ static const struct iio_info ad7195_info = {
IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \
.address = _address, \
.scan_index = _si, \
- .scan_type = IIO_ST('s', 24, 32, 0)}
+ .scan_type = IIO_ST('u', 24, 32, 0)}
static const struct iio_chan_spec ad7192_channels[] = {
AD7192_CHAN_DIFF(1, 2, NULL, AD7192_CH_AIN1P_AIN2M, 0),
--
1.7.10.4
^ permalink raw reply related [flat|nested] 37+ messages in thread
* [PATCH 11/22] staging:iio:ad7192: Report channel offset
2012-08-10 16:36 [PATCH 01/22] staging:iio:ad7793: Add missing break in switch statement Lars-Peter Clausen
` (8 preceding siblings ...)
2012-08-10 16:36 ` [PATCH 10/22] staging:iio:ad7192: Mark channels as unsigned Lars-Peter Clausen
@ 2012-08-10 16:36 ` Lars-Peter Clausen
2012-08-10 16:36 ` [PATCH 12/22] staging:iio:ad7192: Report offset and scale for temperature channel Lars-Peter Clausen
` (10 subsequent siblings)
20 siblings, 0 replies; 37+ messages in thread
From: Lars-Peter Clausen @ 2012-08-10 16:36 UTC (permalink / raw)
To: Jonathan Cameron; +Cc: linux-iio, drivers, Lars-Peter Clausen
In bipolar mode there is a a binary offset of 2**(N-1) (with N being the number
of bits) on the reported value. Currently this value is subtracted when doing a
manual read. While this works for manual channel readings it does not work for
buffered mode. So report the offset in the channels offset property, which will
work in both modes.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
---
drivers/staging/iio/adc/ad7192.c | 14 ++++++++++----
1 file changed, 10 insertions(+), 4 deletions(-)
diff --git a/drivers/staging/iio/adc/ad7192.c b/drivers/staging/iio/adc/ad7192.c
index b103f58..fb59d36 100644
--- a/drivers/staging/iio/adc/ad7192.c
+++ b/drivers/staging/iio/adc/ad7192.c
@@ -826,8 +826,6 @@ static int ad7192_read_raw(struct iio_dev *indio_dev,
switch (chan->type) {
case IIO_VOLTAGE:
- if (!unipolar)
- *val -= (1 << (chan->scan_type.realbits - 1));
break;
case IIO_TEMP:
*val -= 0x800000;
@@ -853,6 +851,12 @@ static int ad7192_read_raw(struct iio_dev *indio_dev,
default:
return -EINVAL;
}
+ case IIO_CHAN_INFO_OFFSET:
+ if (!unipolar)
+ *val -= (1 << (chan->scan_type.realbits - 1));
+ else
+ *val = 0;
+ return IIO_VAL_INT;
}
return -EINVAL;
@@ -942,7 +946,8 @@ static const struct iio_info ad7195_info = {
.channel = _chan, \
.channel2 = _chan2, \
.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
- IIO_CHAN_INFO_SCALE_SHARED_BIT, \
+ IIO_CHAN_INFO_SCALE_SHARED_BIT | \
+ IIO_CHAN_INFO_OFFSET_SHARED_BIT, \
.address = _address, \
.scan_index = _si, \
.scan_type = IIO_ST('u', 24, 32, 0)}
@@ -952,7 +957,8 @@ static const struct iio_info ad7195_info = {
.indexed = 1, \
.channel = _chan, \
.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
- IIO_CHAN_INFO_SCALE_SHARED_BIT, \
+ IIO_CHAN_INFO_SCALE_SHARED_BIT | \
+ IIO_CHAN_INFO_OFFSET_SHARED_BIT, \
.address = _address, \
.scan_index = _si, \
.scan_type = IIO_ST('u', 24, 32, 0)}
--
1.7.10.4
^ permalink raw reply related [flat|nested] 37+ messages in thread
* [PATCH 12/22] staging:iio:ad7192: Report offset and scale for temperature channel
2012-08-10 16:36 [PATCH 01/22] staging:iio:ad7793: Add missing break in switch statement Lars-Peter Clausen
` (9 preceding siblings ...)
2012-08-10 16:36 ` [PATCH 11/22] staging:iio:ad7192: Report channel offset Lars-Peter Clausen
@ 2012-08-10 16:36 ` Lars-Peter Clausen
2012-08-10 16:36 ` [PATCH 13/22] staging:iio:ad7192: Remove unused platform_data from device state struct Lars-Peter Clausen
` (9 subsequent siblings)
20 siblings, 0 replies; 37+ messages in thread
From: Lars-Peter Clausen @ 2012-08-10 16:36 UTC (permalink / raw)
To: Jonathan Cameron; +Cc: linux-iio, drivers, Lars-Peter Clausen
The temperature channel reports values in degree Kelvin with sensitivity of 5630
codes per degree. If the chip is configured in bipolar mode there is an
additional binary offset of 0x800000 and the sensitivity is divided by two.
Currently the driver does the mapping from the raw value to degree Celsius when
doing a manual conversion. This has several disadvantages, the major one being
that it does not work for buffered mode, also by doing the division by the
sensitivity in the driver the precession of the reported value is needlessly
reduced.
Furthermore the current calculation only works in bipolar mode and the current
scale is of by a factor of 1000.
This patch modifies the driver to report correct offset and scale values in
both unipolar and bipolar mode and to report the raw temperature value
for manual conversions.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
---
drivers/staging/iio/adc/ad7192.c | 26 ++++++++++++--------------
1 file changed, 12 insertions(+), 14 deletions(-)
diff --git a/drivers/staging/iio/adc/ad7192.c b/drivers/staging/iio/adc/ad7192.c
index fb59d36..405d9a8 100644
--- a/drivers/staging/iio/adc/ad7192.c
+++ b/drivers/staging/iio/adc/ad7192.c
@@ -798,6 +798,11 @@ static const struct attribute_group ad7195_attribute_group = {
.attrs = ad7195_attributes,
};
+static unsigned int ad7192_get_temp_scale(bool unipolar)
+{
+ return unipolar ? 2815 * 2 : 2815;
+}
+
static int ad7192_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val,
@@ -824,17 +829,6 @@ static int ad7192_read_raw(struct iio_dev *indio_dev,
*val = (smpl >> chan->scan_type.shift) &
((1 << (chan->scan_type.realbits)) - 1);
- switch (chan->type) {
- case IIO_VOLTAGE:
- break;
- case IIO_TEMP:
- *val -= 0x800000;
- *val /= 2815; /* temp Kelvin */
- *val -= 273; /* temp Celsius */
- break;
- default:
- return -EINVAL;
- }
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
@@ -846,16 +840,20 @@ static int ad7192_read_raw(struct iio_dev *indio_dev,
mutex_unlock(&indio_dev->mlock);
return IIO_VAL_INT_PLUS_NANO;
case IIO_TEMP:
- *val = 1000;
- return IIO_VAL_INT;
+ *val = 0;
+ *val2 = 1000000000 / ad7192_get_temp_scale(unipolar);
+ return IIO_VAL_INT_PLUS_NANO;
default:
return -EINVAL;
}
case IIO_CHAN_INFO_OFFSET:
if (!unipolar)
- *val -= (1 << (chan->scan_type.realbits - 1));
+ *val = -(1 << (chan->scan_type.realbits - 1));
else
*val = 0;
+ /* Kelvin to Celsius */
+ if (chan->type == IIO_TEMP)
+ *val -= 273 * ad7192_get_temp_scale(unipolar);
return IIO_VAL_INT;
}
--
1.7.10.4
^ permalink raw reply related [flat|nested] 37+ messages in thread
* [PATCH 13/22] staging:iio:ad7192: Remove unused platform_data from device state struct
2012-08-10 16:36 [PATCH 01/22] staging:iio:ad7793: Add missing break in switch statement Lars-Peter Clausen
` (10 preceding siblings ...)
2012-08-10 16:36 ` [PATCH 12/22] staging:iio:ad7192: Report offset and scale for temperature channel Lars-Peter Clausen
@ 2012-08-10 16:36 ` Lars-Peter Clausen
2012-08-10 16:36 ` [PATCH 14/22] staging:iio:ad7780: Mark channels as unsigned Lars-Peter Clausen
` (8 subsequent siblings)
20 siblings, 0 replies; 37+ messages in thread
From: Lars-Peter Clausen @ 2012-08-10 16:36 UTC (permalink / raw)
To: Jonathan Cameron; +Cc: linux-iio, drivers, Lars-Peter Clausen
The platform data for the device is only used from within the drivers probe
callback, so there is no need to keep it around in the devices state struct.
While we are at it mark the platform data struct as const.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
---
drivers/staging/iio/adc/ad7192.c | 11 ++++-------
1 file changed, 4 insertions(+), 7 deletions(-)
diff --git a/drivers/staging/iio/adc/ad7192.c b/drivers/staging/iio/adc/ad7192.c
index 405d9a8..cdb4fc4 100644
--- a/drivers/staging/iio/adc/ad7192.c
+++ b/drivers/staging/iio/adc/ad7192.c
@@ -136,7 +136,6 @@ struct ad7192_state {
struct spi_device *spi;
struct iio_trigger *trig;
struct regulator *reg;
- struct ad7192_platform_data *pdata;
wait_queue_head_t wq_data_avail;
bool done;
bool irq_dis;
@@ -347,10 +346,10 @@ out:
return ret;
}
-static int ad7192_setup(struct ad7192_state *st)
+static int ad7192_setup(struct ad7192_state *st,
+ const struct ad7192_platform_data *pdata)
{
struct iio_dev *indio_dev = spi_get_drvdata(st->spi);
- struct ad7192_platform_data *pdata = st->pdata;
unsigned long long scale_uv;
int i, ret, id;
u8 ones[6];
@@ -985,7 +984,7 @@ static const struct iio_chan_spec ad7192_channels[] = {
static int __devinit ad7192_probe(struct spi_device *spi)
{
- struct ad7192_platform_data *pdata = spi->dev.platform_data;
+ const struct ad7192_platform_data *pdata = spi->dev.platform_data;
struct ad7192_state *st;
struct iio_dev *indio_dev;
int ret , voltage_uv = 0;
@@ -1015,8 +1014,6 @@ static int __devinit ad7192_probe(struct spi_device *spi)
voltage_uv = regulator_get_voltage(st->reg);
}
- st->pdata = pdata;
-
if (pdata && pdata->vref_mv)
st->int_vref_mv = pdata->vref_mv;
else if (voltage_uv)
@@ -1047,7 +1044,7 @@ static int __devinit ad7192_probe(struct spi_device *spi)
if (ret)
goto error_ring_cleanup;
- ret = ad7192_setup(st);
+ ret = ad7192_setup(st, pdata);
if (ret)
goto error_remove_trigger;
--
1.7.10.4
^ permalink raw reply related [flat|nested] 37+ messages in thread
* [PATCH 14/22] staging:iio:ad7780: Mark channels as unsigned
2012-08-10 16:36 [PATCH 01/22] staging:iio:ad7793: Add missing break in switch statement Lars-Peter Clausen
` (11 preceding siblings ...)
2012-08-10 16:36 ` [PATCH 13/22] staging:iio:ad7192: Remove unused platform_data from device state struct Lars-Peter Clausen
@ 2012-08-10 16:36 ` Lars-Peter Clausen
2012-08-10 16:36 ` [PATCH 15/22] iio: Introduce iio_device_{set,get}_drvdata() Lars-Peter Clausen
` (7 subsequent siblings)
20 siblings, 0 replies; 37+ messages in thread
From: Lars-Peter Clausen @ 2012-08-10 16:36 UTC (permalink / raw)
To: Jonathan Cameron; +Cc: linux-iio, drivers, Lars-Peter Clausen
The values reported by the AD7780 are unsigned with a binary offset:
0x000000 is negative fullscale
0x800000 is zeroscale
0xffffff is positive fullscale
So mark the channel in the channel spec as unsigned rather than signed.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
---
drivers/staging/iio/adc/ad7780.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/drivers/staging/iio/adc/ad7780.c b/drivers/staging/iio/adc/ad7780.c
index 1ece2ac..19ee49c 100644
--- a/drivers/staging/iio/adc/ad7780.c
+++ b/drivers/staging/iio/adc/ad7780.c
@@ -131,9 +131,10 @@ static const struct ad7780_chip_info ad7780_chip_info_tbl[] = {
.indexed = 1,
.channel = 0,
.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
- IIO_CHAN_INFO_SCALE_SHARED_BIT,
+ IIO_CHAN_INFO_SCALE_SHARED_BIT |
+ IIO_CHAN_INFO_OFFSET_SHARED_BIT,
.scan_type = {
- .sign = 's',
+ .sign = 'u',
.realbits = 24,
.storagebits = 32,
.shift = 8,
@@ -146,9 +147,10 @@ static const struct ad7780_chip_info ad7780_chip_info_tbl[] = {
.indexed = 1,
.channel = 0,
.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
- IIO_CHAN_INFO_SCALE_SHARED_BIT,
+ IIO_CHAN_INFO_SCALE_SHARED_BIT |
+ IIO_CHAN_INFO_OFFSET_SHARED_BIT,
.scan_type = {
- .sign = 's',
+ .sign = 'u',
.realbits = 20,
.storagebits = 32,
.shift = 12,
--
1.7.10.4
^ permalink raw reply related [flat|nested] 37+ messages in thread
* [PATCH 15/22] iio: Introduce iio_device_{set,get}_drvdata()
2012-08-10 16:36 [PATCH 01/22] staging:iio:ad7793: Add missing break in switch statement Lars-Peter Clausen
` (12 preceding siblings ...)
2012-08-10 16:36 ` [PATCH 14/22] staging:iio:ad7780: Mark channels as unsigned Lars-Peter Clausen
@ 2012-08-10 16:36 ` Lars-Peter Clausen
2012-08-10 16:36 ` [PATCH 16/22] iio:adc: Add common code for ADI Sigma Delta devices Lars-Peter Clausen
` (6 subsequent siblings)
20 siblings, 0 replies; 37+ messages in thread
From: Lars-Peter Clausen @ 2012-08-10 16:36 UTC (permalink / raw)
To: Jonathan Cameron; +Cc: linux-iio, drivers, Lars-Peter Clausen
Introduce two new helper functions to attach a arbitrary pointer to a IIO
device. This is useful to get access to external non-global data from within a
IIO device callbacks where only the IIO device is available.
Internally these functions use dev_{set,get}_drvdata() on the struct device
embedded in the IIO device.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
---
include/linux/iio/iio.h | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)
diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h
index be82936..b18e74e 100644
--- a/include/linux/iio/iio.h
+++ b/include/linux/iio/iio.h
@@ -516,6 +516,31 @@ static inline struct iio_dev *iio_device_get(struct iio_dev *indio_dev)
return indio_dev ? dev_to_iio_dev(get_device(&indio_dev->dev)) : NULL;
}
+
+/**
+ * iio_device_set_drvdata() - Set device driver data
+ * @indio_dev: IIO device structure
+ * @data: Driver specific data
+ *
+ * Allows to attach an arbitrary pointer to an IIO device, which can later be
+ * retrieved by iio_device_get_drvdata().
+ */
+static inline void iio_device_set_drvdata(struct iio_dev *indio_dev, void *data)
+{
+ dev_set_drvdata(&indio_dev->dev, data);
+}
+
+/**
+ * iio_device_get_drvdata() - Get device driver data
+ * @indio_dev: IIO device structure
+ *
+ * Returns the data previously set with iio_device_set_drvdata()
+ */
+static inline void *iio_device_get_drvdata(struct iio_dev *indio_dev)
+{
+ return dev_get_drvdata(&indio_dev->dev);
+}
+
/* Can we make this smaller? */
#define IIO_ALIGN L1_CACHE_BYTES
/**
--
1.7.10.4
^ permalink raw reply related [flat|nested] 37+ messages in thread
* [PATCH 16/22] iio:adc: Add common code for ADI Sigma Delta devices
2012-08-10 16:36 [PATCH 01/22] staging:iio:ad7793: Add missing break in switch statement Lars-Peter Clausen
` (13 preceding siblings ...)
2012-08-10 16:36 ` [PATCH 15/22] iio: Introduce iio_device_{set,get}_drvdata() Lars-Peter Clausen
@ 2012-08-10 16:36 ` Lars-Peter Clausen
2012-08-14 12:03 ` Jonathan Cameron
2012-08-14 20:19 ` Jonathan Cameron
2012-08-10 16:36 ` [PATCH 17/22] staging:iio:ad7780: Use common Sigma Delta library Lars-Peter Clausen
` (5 subsequent siblings)
20 siblings, 2 replies; 37+ messages in thread
From: Lars-Peter Clausen @ 2012-08-10 16:36 UTC (permalink / raw)
To: Jonathan Cameron; +Cc: linux-iio, drivers, Lars-Peter Clausen
Most devices from the Analog Devices Sigma Delta family use a similar scheme for
communication with the device. This includes register access, as well as trigger
handling. But each device sub-family has different features and different
register layouts (some even have no registers at all) and thus it is impractical
to try to support all of the devices by the same driver. This patch adds a
common base library for Sigma Delta converter devices. It will be used by
individual drivers.
This code is mostly based on the three existing Sigma Delta drivers the AD7192,
AD7780 and AD7793, but has been improved for more robustness and flexibility.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
---
drivers/iio/adc/Kconfig | 5 +
drivers/iio/adc/Makefile | 1 +
drivers/iio/adc/ad_sigma_delta.c | 557 ++++++++++++++++++++++++++++++++
include/linux/iio/adc/ad_sigma_delta.h | 173 ++++++++++
4 files changed, 736 insertions(+)
create mode 100644 drivers/iio/adc/ad_sigma_delta.c
create mode 100644 include/linux/iio/adc/ad_sigma_delta.h
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 8a78b4f..a2c5071 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -3,6 +3,11 @@
#
menu "Analog to digital converters"
+config AD_SIGMA_DELTA
+ tristate
+ select IIO_BUFFER
+ select IIO_TRIGGERED_BUFFER
+
config AD7266
tristate "Analog Devices AD7265/AD7266 ADC driver"
depends on SPI_MASTER
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
index 52eec25..5989356 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -2,5 +2,6 @@
# Makefile for IIO ADC drivers
#
+obj-$(CONFIG_AD_SIGMA_DELTA) += ad_sigma_delta.o
obj-$(CONFIG_AD7266) += ad7266.o
obj-$(CONFIG_AT91_ADC) += at91_adc.o
diff --git a/drivers/iio/adc/ad_sigma_delta.c b/drivers/iio/adc/ad_sigma_delta.c
new file mode 100644
index 0000000..555feb7
--- /dev/null
+++ b/drivers/iio/adc/ad_sigma_delta.c
@@ -0,0 +1,557 @@
+/*
+ * Support code for Analog Devices Sigma-Delta ADCs
+ *
+ * Copyright 2012 Analog Devices Inc.
+ * Author: Lars-Peter Clausen <lars@metafoo.de>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/spi/spi.h>
+#include <linux/err.h>
+#include <linux/module.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
+#include <linux/iio/adc/ad_sigma_delta.h>
+
+#include <asm/unaligned.h>
+
+
+#define AD_SD_COMM_CHAN_MASK 0x3
+
+#define AD_SD_REG_COMM 0x00
+#define AD_SD_REG_DATA 0x03
+
+/**
+ * ad_sd_set_comm() - Set communications register
+ *
+ * @sigma_delta: The sigma delta device
+ * @comm: New value for the communications register
+ */
+void ad_sd_set_comm(struct ad_sigma_delta *sigma_delta, uint8_t comm)
+{
+ /* Some variants use the lower two bits of the communications register
+ * to select the channel */
+ sigma_delta->comm = comm & AD_SD_COMM_CHAN_MASK;
+}
+EXPORT_SYMBOL_GPL(ad_sd_set_comm);
+
+/**
+ * ad_sd_write_reg() - Write a register
+ *
+ * @sigma_delta: The sigma delta device
+ * @reg: Address of the register
+ * @size: Size of the register (0-3)
+ * @val: Value to write to the register
+ *
+ * Returns 0 on success, an error code otherwise.
+ **/
+int ad_sd_write_reg(struct ad_sigma_delta *sigma_delta, unsigned int reg,
+ unsigned int size, unsigned int val)
+{
+ uint8_t *data = sigma_delta->data;
+ struct spi_transfer t = {
+ .tx_buf = data,
+ .len = size + 1,
+ .cs_change = sigma_delta->bus_locked,
+ };
+ struct spi_message m;
+ int ret;
+
+ data[0] = (reg << sigma_delta->info->addr_shift) | sigma_delta->comm;
+
+ switch (size) {
+ case 3:
+ data[1] = val >> 16;
+ data[2] = val >> 8;
+ data[3] = val;
+ break;
+ case 2:
+ put_unaligned_be16(val, &data[1]);
+ break;
+ case 1:
+ data[1] = val;
+ break;
+ case 0:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ spi_message_init(&m);
+ spi_message_add_tail(&t, &m);
+
+ if (sigma_delta->bus_locked)
+ ret = spi_sync_locked(sigma_delta->spi, &m);
+ else
+ ret = spi_sync(sigma_delta->spi, &m);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(ad_sd_write_reg);
+
+static int ad_sd_read_reg_raw(struct ad_sigma_delta *sigma_delta,
+ unsigned int reg, unsigned int size, uint8_t *val)
+{
+ uint8_t *data = sigma_delta->data;
+ int ret;
+ struct spi_transfer t[] = {
+ {
+ .tx_buf = data,
+ .len = 1,
+ }, {
+ .rx_buf = val,
+ .len = size,
+ .cs_change = sigma_delta->bus_locked,
+ },
+ };
+ struct spi_message m;
+
+ spi_message_init(&m);
+
+ if (sigma_delta->info->has_registers) {
+ data[0] = reg << sigma_delta->info->addr_shift;
+ data[0] |= sigma_delta->info->read_mask;
+ spi_message_add_tail(&t[0], &m);
+ }
+ spi_message_add_tail(&t[1], &m);
+
+ if (sigma_delta->bus_locked)
+ ret = spi_sync_locked(sigma_delta->spi, &m);
+ else
+ ret = spi_sync(sigma_delta->spi, &m);
+
+ return ret;
+}
+
+/**
+ * ad_sd_read_reg() - Read a register
+ *
+ * @sigma_delta: The sigma delta device
+ * @reg: Address of the register
+ * @size: Size of the register (1-4)
+ * @val: Read value
+ *
+ * Returns 0 on success, an error code otherwise.
+ **/
+int ad_sd_read_reg(struct ad_sigma_delta *sigma_delta,
+ unsigned int reg, unsigned int size, unsigned int *val)
+{
+ int ret;
+
+ ret = ad_sd_read_reg_raw(sigma_delta, reg, size, sigma_delta->data);
+ if (ret < 0)
+ goto out;
+
+ switch (size) {
+ case 4:
+ *val = get_unaligned_be32(sigma_delta->data);
+ break;
+ case 3:
+ *val = (sigma_delta->data[0] << 16) |
+ (sigma_delta->data[1] << 8) |
+ sigma_delta->data[2];
+ break;
+ case 2:
+ *val = get_unaligned_be16(sigma_delta->data);
+ break;
+ case 1:
+ *val = sigma_delta->data[0];
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+out:
+ return ret;
+}
+EXPORT_SYMBOL_GPL(ad_sd_read_reg);
+
+static int ad_sd_calibrate(struct ad_sigma_delta *sigma_delta,
+ unsigned int mode, unsigned int channel)
+{
+ int ret;
+
+ ret = ad_sigma_delta_set_channel(sigma_delta, channel);
+ if (ret)
+ return ret;
+
+ spi_bus_lock(sigma_delta->spi->master);
+ sigma_delta->bus_locked = true;
+ INIT_COMPLETION(sigma_delta->completion);
+
+ ret = ad_sigma_delta_set_mode(sigma_delta, mode);
+ if (ret < 0)
+ goto out;
+
+ sigma_delta->irq_dis = false;
+ enable_irq(sigma_delta->spi->irq);
+ ret = wait_for_completion_timeout(&sigma_delta->completion, 2*HZ);
+ if (ret == 0) {
+ sigma_delta->irq_dis = true;
+ disable_irq_nosync(sigma_delta->spi->irq);
+ ret = -EIO;
+ } else {
+ ret = 0;
+ }
+out:
+ sigma_delta->bus_locked = false;
+ spi_bus_unlock(sigma_delta->spi->master);
+ ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_IDLE);
+
+ return ret;
+}
+
+/**
+ * ad_sd_calibrate_all() - Performs channel calibration
+ * @sigma_delta: The sigma delta device
+ * @cb: Array of channels and calibration type to perform
+ * @n: Number of items in cb
+ *
+ * Returns 0 on success, an error code otherwise.
+ **/
+int ad_sd_calibrate_all(struct ad_sigma_delta *sigma_delta,
+ const struct ad_sd_calib_data *cb, unsigned int n)
+{
+ unsigned int i;
+ int ret;
+
+ for (i = 0; i < n; i++) {
+ ret = ad_sd_calibrate(sigma_delta, cb[i].mode, cb[i].channel);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(ad_sd_calibrate_all);
+
+/**
+ * ad_sigma_delta_single_conversion() - Performs a single data conversion
+ * @indio_dev: The IIO device
+ * @chan: The conversion is done for this channel
+ * @val: Pointer to the location where to store the read value
+ *
+ * Returns: 0 on success, an error value otherwise.
+ */
+int ad_sigma_delta_single_conversion(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan, int *val)
+{
+ struct ad_sigma_delta *sigma_delta = iio_device_get_drvdata(indio_dev);
+ unsigned int sample, raw_sample;
+ int ret = 0;
+
+ if (iio_buffer_enabled(indio_dev))
+ return -EBUSY;
+
+ mutex_lock(&indio_dev->mlock);
+ ad_sigma_delta_set_channel(sigma_delta, chan->address);
+
+ spi_bus_lock(sigma_delta->spi->master);
+ sigma_delta->bus_locked = true;
+ INIT_COMPLETION(sigma_delta->completion);
+
+ ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_SINGLE);
+
+ sigma_delta->irq_dis = false;
+ enable_irq(sigma_delta->spi->irq);
+ ret = wait_for_completion_interruptible_timeout(
+ &sigma_delta->completion, HZ);
+
+ sigma_delta->bus_locked = false;
+ spi_bus_unlock(sigma_delta->spi->master);
+
+ if (ret == 0)
+ ret = -EIO;
+ if (ret < 0)
+ goto out;
+
+ ret = ad_sd_read_reg(sigma_delta, AD_SD_REG_DATA,
+ DIV_ROUND_UP(chan->scan_type.realbits + chan->scan_type.shift, 8),
+ &raw_sample);
+
+out:
+ if (!sigma_delta->irq_dis) {
+ disable_irq_nosync(sigma_delta->spi->irq);
+ sigma_delta->irq_dis = true;
+ }
+
+ ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_IDLE);
+ mutex_unlock(&indio_dev->mlock);
+
+ if (ret)
+ return ret;
+
+ sample = raw_sample >> chan->scan_type.shift;
+ sample &= (1 << chan->scan_type.realbits) - 1;
+ *val = sample;
+
+ ret = ad_sigma_delta_postprocess_sample(sigma_delta, raw_sample);
+ if (ret)
+ return ret;
+
+ return IIO_VAL_INT;
+}
+EXPORT_SYMBOL_GPL(ad_sigma_delta_single_conversion);
+
+static int ad_sd_buffer_postenable(struct iio_dev *indio_dev)
+{
+ struct ad_sigma_delta *sigma_delta = iio_device_get_drvdata(indio_dev);
+ unsigned int channel;
+ int ret;
+
+ ret = iio_triggered_buffer_postenable(indio_dev);
+ if (ret < 0)
+ return ret;
+
+ channel = find_first_bit(indio_dev->active_scan_mask,
+ indio_dev->masklength);
+ ret = ad_sigma_delta_set_channel(sigma_delta,
+ indio_dev->channels[channel].address);
+ if (ret)
+ goto err_predisable;
+
+ spi_bus_lock(sigma_delta->spi->master);
+ sigma_delta->bus_locked = true;
+ ret = ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_CONTINUOUS);
+ if (ret)
+ goto err_unlock;
+
+ sigma_delta->irq_dis = false;
+ enable_irq(sigma_delta->spi->irq);
+
+ return 0;
+
+err_unlock:
+ spi_bus_unlock(sigma_delta->spi->master);
+err_predisable:
+
+ return ret;
+}
+
+static int ad_sd_buffer_postdisable(struct iio_dev *indio_dev)
+{
+ struct ad_sigma_delta *sigma_delta = iio_device_get_drvdata(indio_dev);
+
+ INIT_COMPLETION(sigma_delta->completion);
+ wait_for_completion_timeout(&sigma_delta->completion, HZ);
+
+ if (!sigma_delta->irq_dis) {
+ disable_irq_nosync(sigma_delta->spi->irq);
+ sigma_delta->irq_dis = true;
+ }
+
+ ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_IDLE);
+
+ sigma_delta->bus_locked = false;
+ return spi_bus_unlock(sigma_delta->spi->master);
+}
+
+static irqreturn_t ad_sd_trigger_handler(int irq, void *p)
+{
+ struct iio_poll_func *pf = p;
+ struct iio_dev *indio_dev = pf->indio_dev;
+ struct ad_sigma_delta *sigma_delta = iio_device_get_drvdata(indio_dev);
+ unsigned int reg_size;
+ uint8_t data[16];
+ int ret;
+
+ memset(data, 0x00, 16);
+
+ /* Guaranteed to be aligned with 8 byte boundary */
+ if (indio_dev->scan_timestamp)
+ ((s64 *)data)[1] = pf->timestamp;
+
+ reg_size = indio_dev->channels[0].scan_type.realbits +
+ indio_dev->channels[0].scan_type.shift;
+ reg_size = DIV_ROUND_UP(reg_size, 8);
+
+ switch (reg_size) {
+ case 4:
+ case 2:
+ case 1:
+ ret = ad_sd_read_reg_raw(sigma_delta, AD_SD_REG_DATA,
+ reg_size, &data[0]);
+ break;
+ case 3:
+ /* We store 24 bit samples in a 32 bit word. Keep the upper
+ * byte set to zero. */
+ ret = ad_sd_read_reg_raw(sigma_delta, AD_SD_REG_DATA,
+ reg_size, &data[1]);
+ break;
+ }
+
+ iio_push_to_buffer(indio_dev->buffer, (uint8_t *)data, pf->timestamp);
+
+ iio_trigger_notify_done(indio_dev->trig);
+ sigma_delta->irq_dis = false;
+ enable_irq(sigma_delta->spi->irq);
+
+ return IRQ_HANDLED;
+}
+
+static const struct iio_buffer_setup_ops ad_sd_buffer_setup_ops = {
+ .preenable = &iio_sw_buffer_preenable,
+ .postenable = &ad_sd_buffer_postenable,
+ .predisable = &iio_triggered_buffer_predisable,
+ .postdisable = &ad_sd_buffer_postdisable,
+ .validate_scan_mask = &iio_validate_scan_mask_onehot,
+};
+
+static irqreturn_t ad_sd_data_rdy_trig_poll(int irq, void *private)
+{
+ struct ad_sigma_delta *sigma_delta = private;
+
+ complete(&sigma_delta->completion);
+ disable_irq_nosync(irq);
+ sigma_delta->irq_dis = true;
+ iio_trigger_poll(sigma_delta->trig, iio_get_time_ns());
+
+ return IRQ_HANDLED;
+}
+
+/**
+ * ad_sd_validate_trigger() - validate_trigger callback for ad_sigma_delta devices
+ * @indio_dev: The IIO device
+ * @trig: The new trigger
+ *
+ * Returns: 0 if the 'trig' matches the trigger registered by the ad_sigma_delta
+ * device, -EINVAL otherwise.
+ */
+int ad_sd_validate_trigger(struct iio_dev *indio_dev, struct iio_trigger *trig)
+{
+ struct ad_sigma_delta *sigma_delta = iio_device_get_drvdata(indio_dev);
+
+ if (sigma_delta->trig != trig)
+ return -EINVAL;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(ad_sd_validate_trigger);
+
+static const struct iio_trigger_ops ad_sd_trigger_ops = {
+ .owner = THIS_MODULE,
+};
+
+static int ad_sd_probe_trigger(struct iio_dev *indio_dev)
+{
+ struct ad_sigma_delta *sigma_delta = iio_device_get_drvdata(indio_dev);
+ int ret;
+
+ sigma_delta->trig = iio_trigger_alloc("%s-dev%d", indio_dev->name,
+ indio_dev->id);
+ if (sigma_delta->trig == NULL) {
+ ret = -ENOMEM;
+ goto error_ret;
+ }
+ sigma_delta->trig->ops = &ad_sd_trigger_ops;
+ init_completion(&sigma_delta->completion);
+
+ ret = request_irq(sigma_delta->spi->irq,
+ ad_sd_data_rdy_trig_poll,
+ IRQF_TRIGGER_LOW,
+ indio_dev->name,
+ sigma_delta);
+ if (ret)
+ goto error_free_trig;
+
+ if (!sigma_delta->irq_dis) {
+ sigma_delta->irq_dis = true;
+ disable_irq_nosync(sigma_delta->spi->irq);
+ }
+ sigma_delta->trig->dev.parent = &sigma_delta->spi->dev;
+ sigma_delta->trig->private_data = sigma_delta;
+
+ ret = iio_trigger_register(sigma_delta->trig);
+ if (ret)
+ goto error_free_irq;
+
+ /* select default trigger */
+ indio_dev->trig = sigma_delta->trig;
+
+ return 0;
+
+error_free_irq:
+ free_irq(sigma_delta->spi->irq, sigma_delta);
+error_free_trig:
+ iio_trigger_free(sigma_delta->trig);
+error_ret:
+ return ret;
+}
+
+static void ad_sd_remove_trigger(struct iio_dev *indio_dev)
+{
+ struct ad_sigma_delta *sigma_delta = iio_device_get_drvdata(indio_dev);
+
+ iio_trigger_unregister(sigma_delta->trig);
+ free_irq(sigma_delta->spi->irq, sigma_delta);
+ iio_trigger_free(sigma_delta->trig);
+}
+
+/**
+ * ad_sd_setup_buffer_and_trigger() -
+ * @indio_dev: The IIO device
+ */
+int ad_sd_setup_buffer_and_trigger(struct iio_dev *indio_dev)
+{
+ int ret;
+
+ ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,
+ &ad_sd_trigger_handler, &ad_sd_buffer_setup_ops);
+ if (ret)
+ return ret;
+
+ ret = ad_sd_probe_trigger(indio_dev);
+ if (ret) {
+ iio_triggered_buffer_cleanup(indio_dev);
+ return ret;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(ad_sd_setup_buffer_and_trigger);
+
+/**
+ * ad_sd_cleanup_buffer_and_trigger() -
+ * @indio_dev: The IIO device
+ */
+void ad_sd_cleanup_buffer_and_trigger(struct iio_dev *indio_dev)
+{
+ ad_sd_remove_trigger(indio_dev);
+ iio_triggered_buffer_cleanup(indio_dev);
+}
+EXPORT_SYMBOL_GPL(ad_sd_cleanup_buffer_and_trigger);
+
+/**
+ * ad_sd_init() - Initializes a ad_sigma_delta struct
+ * @sigma_delta: The ad_sigma_delta device
+ * @indio_dev: The IIO device which the Sigma Delta device is used for
+ * @spi: The SPI device for the ad_sigma_delta device
+ * @info: Device specific callbacks and options
+ *
+ * This function needs to be called before any other operations are performed on
+ * the ad_sigma_delta struct.
+ */
+int ad_sd_init(struct ad_sigma_delta *sigma_delta, struct iio_dev *indio_dev,
+ struct spi_device *spi, const struct ad_sigma_delta_info *info)
+{
+ sigma_delta->spi = spi;
+ sigma_delta->info = info;
+ iio_device_set_drvdata(indio_dev, sigma_delta);
+
+ return 0;
+}
+
+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
+MODULE_DESCRIPTION("Analog Devices Sigma-Delta ADCs");
+MODULE_LICENSE("GPL v2");
diff --git a/include/linux/iio/adc/ad_sigma_delta.h b/include/linux/iio/adc/ad_sigma_delta.h
new file mode 100644
index 0000000..2e4eab9
--- /dev/null
+++ b/include/linux/iio/adc/ad_sigma_delta.h
@@ -0,0 +1,173 @@
+/*
+ * Support code for Analog Devices Sigma-Delta ADCs
+ *
+ * Copyright 2012 Analog Devices Inc.
+ * Author: Lars-Peter Clausen <lars@metafoo.de>
+ *
+ * Licensed under the GPL-2.
+ */
+#ifndef __AD_SIGMA_DELTA_H__
+#define __AD_SIGMA_DELTA_H__
+
+enum ad_sigma_delta_mode {
+ AD_SD_MODE_CONTINUOUS = 0,
+ AD_SD_MODE_SINGLE = 1,
+ AD_SD_MODE_IDLE = 2,
+ AD_SD_MODE_POWERDOWN = 3,
+};
+
+/**
+ * struct ad_sigma_delta_calib_data - Calibration data for Sigma Delta devices
+ * @mode: Calibration mode.
+ * @channel: Calibration channel.
+ */
+struct ad_sd_calib_data {
+ unsigned int mode;
+ unsigned int channel;
+};
+
+struct ad_sigma_delta;
+struct iio_dev;
+
+/**
+ * struct ad_sigma_delta_info - Sigma Delta driver specific callbacks and options
+ * @set_channel: Will be called to select the current channel, may be NULL.
+ * @set_mode: Will be called to select the current mode, may be NULL.
+ * @postprocess_sample: Is called for each sampled data word, can be used to
+ * modify or drop the sample data, it, may be NULL.
+ * @has_registers: true if the device has writable and readable registers, false
+ * if there is just one read-only sample data shift register.
+ * @addr_shift: Shift of the register address in the communications register.
+ * @read_mask: Mask for the communications register having the read bit set.
+ */
+struct ad_sigma_delta_info {
+ int (*set_channel)(struct ad_sigma_delta *, unsigned int channel);
+ int (*set_mode)(struct ad_sigma_delta *, enum ad_sigma_delta_mode mode);
+ int (*postprocess_sample)(struct ad_sigma_delta *, unsigned int raw_sample);
+ bool has_registers;
+ unsigned int addr_shift;
+ unsigned int read_mask;
+};
+
+/**
+ * struct ad_sigma_delta - Sigma Delta device struct
+ * @spi: The spi device associated with the Sigma Delta device.
+ * @trig: The IIO trigger associated with the Sigma Delta device.
+ *
+ * Most of the fields are private to the sigma delta library code and should not
+ * be accessed by individual drivers.
+ */
+struct ad_sigma_delta {
+ struct spi_device *spi;
+ struct iio_trigger *trig;
+
+/* private: */
+ struct completion completion;
+ bool irq_dis;
+
+ bool bus_locked;
+
+ uint8_t comm;
+
+ const struct ad_sigma_delta_info *info;
+
+ /*
+ * DMA (thus cache coherency maintenance) requires the
+ * transfer buffers to live in their own cache lines.
+ */
+ uint8_t data[4] ____cacheline_aligned;
+};
+
+static inline int ad_sigma_delta_set_channel(struct ad_sigma_delta *sd,
+ unsigned int channel)
+{
+ if (sd->info->set_channel)
+ return sd->info->set_channel(sd, channel);
+
+ return 0;
+}
+
+static inline int ad_sigma_delta_set_mode(struct ad_sigma_delta *sd,
+ unsigned int mode)
+{
+ if (sd->info->set_mode)
+ return sd->info->set_mode(sd, mode);
+
+ return 0;
+}
+
+static inline int ad_sigma_delta_postprocess_sample(struct ad_sigma_delta *sd,
+ unsigned int raw_sample)
+{
+ if (sd->info->postprocess_sample)
+ return sd->info->postprocess_sample(sd, raw_sample);
+
+ return 0;
+}
+
+void ad_sd_set_comm(struct ad_sigma_delta *sigma_delta, uint8_t comm);
+int ad_sd_write_reg(struct ad_sigma_delta *sigma_delta, unsigned int reg,
+ unsigned int size, unsigned int val);
+int ad_sd_read_reg(struct ad_sigma_delta *sigma_delta, unsigned int reg,
+ unsigned int size, unsigned int *val);
+
+int ad_sigma_delta_single_conversion(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan, int *val);
+int ad_sd_calibrate_all(struct ad_sigma_delta *sigma_delta,
+ const struct ad_sd_calib_data *cd, unsigned int n);
+int ad_sd_init(struct ad_sigma_delta *sigma_delta, struct iio_dev *indio_dev,
+ struct spi_device *spi, const struct ad_sigma_delta_info *info);
+
+int ad_sd_setup_buffer_and_trigger(struct iio_dev *indio_dev);
+void ad_sd_cleanup_buffer_and_trigger(struct iio_dev *indio_dev);
+
+int ad_sd_validate_trigger(struct iio_dev *indio_dev, struct iio_trigger *trig);
+
+#define __AD_SD_CHANNEL(_si, _channel1, _channel2, _address, _bits, \
+ _storagebits, _shift, _extend_name, _type) \
+ { \
+ .type = (_type), \
+ .differential = (_channel2 == -1 ? 0 : 1), \
+ .indexed = 1, \
+ .channel = (_channel1), \
+ .channel2 = (_channel2), \
+ .address = (_address), \
+ .extend_name = (_extend_name), \
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
+ IIO_CHAN_INFO_SCALE_SHARED_BIT | \
+ IIO_CHAN_INFO_OFFSET_SEPARATE_BIT, \
+ .scan_index = (_si), \
+ .scan_type = { \
+ .sign = 'u', \
+ .realbits = (_bits), \
+ .storagebits = (_storagebits), \
+ .shift = (_shift), \
+ .endianness = IIO_BE, \
+ }, \
+ }
+
+#define AD_SD_DIFF_CHANNEL(_si, _channel1, _channel2, _address, _bits, \
+ _storagebits, _shift) \
+ __AD_SD_CHANNEL(_si, _channel1, _channel2, _address, _bits, \
+ _storagebits, _shift, NULL, IIO_VOLTAGE)
+
+#define AD_SD_SHORTED_CHANNEL(_si, _channel, _address, _bits, \
+ _storagebits, _shift) \
+ __AD_SD_CHANNEL(_si, _channel, _channel, _address, _bits, \
+ _storagebits, _shift, "shorted", IIO_VOLTAGE)
+
+#define AD_SD_CHANNEL(_si, _channel, _address, _bits, \
+ _storagebits, _shift) \
+ __AD_SD_CHANNEL(_si, _channel, -1, _address, _bits, \
+ _storagebits, _shift, NULL, IIO_VOLTAGE)
+
+#define AD_SD_TEMP_CHANNEL(_si, _address, _bits, _storagebits, _shift) \
+ __AD_SD_CHANNEL(_si, 0, -1, _address, _bits, \
+ _storagebits, _shift, NULL, IIO_TEMP)
+
+#define AD_SD_SUPPLY_CHANNEL(_si, _channel, _address, _bits, _storagebits, \
+ _shift) \
+ __AD_SD_CHANNEL(_si, _channel, -1, _address, _bits, \
+ _storagebits, _shift, "supply", IIO_VOLTAGE)
+
+#endif
--
1.7.10.4
^ permalink raw reply related [flat|nested] 37+ messages in thread
* [PATCH 17/22] staging:iio:ad7780: Use common Sigma Delta library
2012-08-10 16:36 [PATCH 01/22] staging:iio:ad7793: Add missing break in switch statement Lars-Peter Clausen
` (14 preceding siblings ...)
2012-08-10 16:36 ` [PATCH 16/22] iio:adc: Add common code for ADI Sigma Delta devices Lars-Peter Clausen
@ 2012-08-10 16:36 ` Lars-Peter Clausen
2012-08-14 12:05 ` Jonathan Cameron
2012-08-10 16:36 ` [PATCH 18/22] staging:iio:ad7793: " Lars-Peter Clausen
` (4 subsequent siblings)
20 siblings, 1 reply; 37+ messages in thread
From: Lars-Peter Clausen @ 2012-08-10 16:36 UTC (permalink / raw)
To: Jonathan Cameron; +Cc: linux-iio, drivers, Lars-Peter Clausen
Convert the ad7780 driver to make use of the new common code for devices from
the Analog Devices Sigma Delta family.
As a bonus the ad7780 driver gains support for buffered mode. Although this is a
bit tricky. The ad7780 reports in the lower 4 unused bits of the data word the
internal gain used. The driver will update the scale attribute value depending
on the gain accordingly, but obviously this will only work if the gain does not
change while sampling. This is not perfect, but since we store the raw value in
the buffer an application which is aware of this can extract the gain factor
from the buffer as well an apply it accordingly.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
---
drivers/staging/iio/adc/Kconfig | 1 +
drivers/staging/iio/adc/ad7780.c | 186 ++++++++++++++------------------------
2 files changed, 71 insertions(+), 116 deletions(-)
diff --git a/drivers/staging/iio/adc/Kconfig b/drivers/staging/iio/adc/Kconfig
index 67711b7..fc7b7f6 100644
--- a/drivers/staging/iio/adc/Kconfig
+++ b/drivers/staging/iio/adc/Kconfig
@@ -99,6 +99,7 @@ config AD7780
tristate "Analog Devices AD7780 AD7781 ADC driver"
depends on SPI
depends on GPIOLIB
+ select AD_SIGMA_DELTA
help
Say yes here to build support for Analog Devices
AD7780 and AD7781 SPI analog to digital converters (ADC).
diff --git a/drivers/staging/iio/adc/ad7780.c b/drivers/staging/iio/adc/ad7780.c
index 19ee49c..853f8b1 100644
--- a/drivers/staging/iio/adc/ad7780.c
+++ b/drivers/staging/iio/adc/ad7780.c
@@ -20,6 +20,7 @@
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
+#include <linux/iio/adc/ad_sigma_delta.h>
#include "ad7780.h"
@@ -37,20 +38,13 @@ struct ad7780_chip_info {
};
struct ad7780_state {
- struct spi_device *spi;
const struct ad7780_chip_info *chip_info;
struct regulator *reg;
- struct ad7780_platform_data *pdata;
- wait_queue_head_t wq_data_avail;
- bool done;
+ int powerdown_gpio;
+ unsigned int gain;
u16 int_vref_mv;
- struct spi_transfer xfer;
- struct spi_message msg;
- /*
- * DMA (thus cache coherency maintenance) requires the
- * transfer buffers to live in their own cache lines.
- */
- unsigned int data ____cacheline_aligned;
+
+ struct ad_sigma_delta sd;
};
enum ad7780_supported_device_ids {
@@ -58,28 +52,30 @@ enum ad7780_supported_device_ids {
ID_AD7781,
};
-static int ad7780_read(struct ad7780_state *st, int *val)
+static struct ad7780_state *ad_sigma_delta_to_ad7780(struct ad_sigma_delta *sd)
{
- int ret;
-
- spi_bus_lock(st->spi->master);
-
- enable_irq(st->spi->irq);
- st->done = false;
- gpio_set_value(st->pdata->gpio_pdrst, 1);
+ return container_of(sd, struct ad7780_state, sd);
+}
- ret = wait_event_interruptible(st->wq_data_avail, st->done);
- disable_irq_nosync(st->spi->irq);
- if (ret)
- goto out;
+static int ad7780_set_mode(struct ad_sigma_delta *sigma_delta,
+ enum ad_sigma_delta_mode mode)
+{
+ struct ad7780_state *st = ad_sigma_delta_to_ad7780(sigma_delta);
+ unsigned val;
+
+ switch (mode) {
+ case AD_SD_MODE_SINGLE:
+ case AD_SD_MODE_CONTINUOUS:
+ val = 1;
+ break;
+ default:
+ val = 0;
+ break;
+ }
- ret = spi_sync_locked(st->spi, &st->msg);
- *val = be32_to_cpu(st->data);
-out:
- gpio_set_value(st->pdata->gpio_pdrst, 0);
- spi_bus_unlock(st->spi->master);
+ gpio_set_value(st->powerdown_gpio, val);
- return ret;
+ return 0;
}
static int ad7780_read_raw(struct iio_dev *indio_dev,
@@ -89,89 +85,57 @@ static int ad7780_read_raw(struct iio_dev *indio_dev,
long m)
{
struct ad7780_state *st = iio_priv(indio_dev);
- struct iio_chan_spec channel = st->chip_info->channel;
- int ret, smpl = 0;
unsigned long scale_uv;
switch (m) {
case IIO_CHAN_INFO_RAW:
- mutex_lock(&indio_dev->mlock);
- ret = ad7780_read(st, &smpl);
- mutex_unlock(&indio_dev->mlock);
-
- if (ret < 0)
- return ret;
-
- if ((smpl & AD7780_ERR) ||
- !((smpl & AD7780_PAT0) && !(smpl & AD7780_PAT1)))
- return -EIO;
-
- *val = (smpl >> channel.scan_type.shift) &
- ((1 << (channel.scan_type.realbits)) - 1);
- *val -= (1 << (channel.scan_type.realbits - 1));
-
- if (!(smpl & AD7780_GAIN))
- *val *= 128;
-
- return IIO_VAL_INT;
+ return ad_sigma_delta_single_conversion(indio_dev, chan, val);
case IIO_CHAN_INFO_SCALE:
- scale_uv = (st->int_vref_mv * 100000)
- >> (channel.scan_type.realbits - 1);
+ scale_uv = (st->int_vref_mv * 100000 * st->gain)
+ >> (chan->scan_type.realbits - 1);
*val = scale_uv / 100000;
*val2 = (scale_uv % 100000) * 10;
return IIO_VAL_INT_PLUS_MICRO;
+ case IIO_CHAN_INFO_OFFSET:
+ *val -= (1 << (chan->scan_type.realbits - 1));
+ return IIO_VAL_INT;
}
+
return -EINVAL;
}
+static int ad7780_postprocess_sample(struct ad_sigma_delta *sigma_delta,
+ unsigned int raw_sample)
+{
+ struct ad7780_state *st = ad_sigma_delta_to_ad7780(sigma_delta);
+
+ if ((raw_sample & AD7780_ERR) ||
+ !((raw_sample & AD7780_PAT0) && !(raw_sample & AD7780_PAT1)))
+ return -EIO;
+
+ if (raw_sample & AD7780_GAIN)
+ st->gain = 1;
+ else
+ st->gain = 128;
+
+ return 0;
+}
+
+static const struct ad_sigma_delta_info ad7780_sigma_delta_info = {
+ .set_mode = ad7780_set_mode,
+ .postprocess_sample = ad7780_postprocess_sample,
+ .has_registers = false,
+};
+
static const struct ad7780_chip_info ad7780_chip_info_tbl[] = {
[ID_AD7780] = {
- .channel = {
- .type = IIO_VOLTAGE,
- .indexed = 1,
- .channel = 0,
- .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
- IIO_CHAN_INFO_SCALE_SHARED_BIT |
- IIO_CHAN_INFO_OFFSET_SHARED_BIT,
- .scan_type = {
- .sign = 'u',
- .realbits = 24,
- .storagebits = 32,
- .shift = 8,
- },
- },
+ .channel = AD_SD_CHANNEL(1, 0, 0, 24, 32, 8),
},
[ID_AD7781] = {
- .channel = {
- .type = IIO_VOLTAGE,
- .indexed = 1,
- .channel = 0,
- .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
- IIO_CHAN_INFO_SCALE_SHARED_BIT |
- IIO_CHAN_INFO_OFFSET_SHARED_BIT,
- .scan_type = {
- .sign = 'u',
- .realbits = 20,
- .storagebits = 32,
- .shift = 12,
- },
- },
+ .channel = AD_SD_CHANNEL(1, 0, 0, 20, 32, 12),
},
};
-/**
- * Interrupt handler
- */
-static irqreturn_t ad7780_interrupt(int irq, void *dev_id)
-{
- struct ad7780_state *st = dev_id;
-
- st->done = true;
- wake_up_interruptible(&st->wq_data_avail);
-
- return IRQ_HANDLED;
-};
-
static const struct iio_info ad7780_info = {
.read_raw = &ad7780_read_raw,
.driver_module = THIS_MODULE,
@@ -194,6 +158,9 @@ static int __devinit ad7780_probe(struct spi_device *spi)
return -ENOMEM;
st = iio_priv(indio_dev);
+ st->gain = 1;
+
+ ad_sd_init(&st->sd, indio_dev, spi, &ad7780_sigma_delta_info);
st->reg = regulator_get(&spi->dev, "vcc");
if (!IS_ERR(st->reg)) {
@@ -207,7 +174,7 @@ static int __devinit ad7780_probe(struct spi_device *spi)
st->chip_info =
&ad7780_chip_info_tbl[spi_get_device_id(spi)->driver_data];
- st->pdata = pdata;
+ st->powerdown_gpio = pdata->gpio_pdrst;
if (pdata && pdata->vref_mv)
st->int_vref_mv = pdata->vref_mv;
@@ -217,7 +184,6 @@ static int __devinit ad7780_probe(struct spi_device *spi)
dev_warn(&spi->dev, "reference voltage unspecified\n");
spi_set_drvdata(spi, indio_dev);
- st->spi = spi;
indio_dev->dev.parent = &spi->dev;
indio_dev->name = spi_get_device_id(spi)->name;
@@ -226,40 +192,27 @@ static int __devinit ad7780_probe(struct spi_device *spi)
indio_dev->num_channels = 1;
indio_dev->info = &ad7780_info;
- init_waitqueue_head(&st->wq_data_avail);
-
- /* Setup default message */
-
- st->xfer.rx_buf = &st->data;
- st->xfer.len = st->chip_info->channel.scan_type.storagebits / 8;
-
- spi_message_init(&st->msg);
- spi_message_add_tail(&st->xfer, &st->msg);
-
- ret = gpio_request_one(st->pdata->gpio_pdrst, GPIOF_OUT_INIT_LOW,
+ ret = gpio_request_one(pdata->gpio_pdrst, GPIOF_OUT_INIT_LOW,
"AD7780 /PDRST");
if (ret) {
dev_err(&spi->dev, "failed to request GPIO PDRST\n");
goto error_disable_reg;
}
- ret = request_irq(spi->irq, ad7780_interrupt,
- IRQF_TRIGGER_FALLING, spi_get_device_id(spi)->name, st);
+ ret = ad_sd_setup_buffer_and_trigger(indio_dev);
if (ret)
goto error_free_gpio;
- disable_irq(spi->irq);
-
ret = iio_device_register(indio_dev);
if (ret)
- goto error_free_irq;
+ goto error_cleanup_buffer_and_trigger;
return 0;
-error_free_irq:
- free_irq(spi->irq, st);
+error_cleanup_buffer_and_trigger:
+ ad_sd_cleanup_buffer_and_trigger(indio_dev);
error_free_gpio:
- gpio_free(st->pdata->gpio_pdrst);
+ gpio_free(pdata->gpio_pdrst);
error_disable_reg:
if (!IS_ERR(st->reg))
regulator_disable(st->reg);
@@ -278,8 +231,9 @@ static int ad7780_remove(struct spi_device *spi)
struct ad7780_state *st = iio_priv(indio_dev);
iio_device_unregister(indio_dev);
- free_irq(spi->irq, st);
- gpio_free(st->pdata->gpio_pdrst);
+ ad_sd_cleanup_buffer_and_trigger(indio_dev);
+
+ gpio_free(st->powerdown_gpio);
if (!IS_ERR(st->reg)) {
regulator_disable(st->reg);
regulator_put(st->reg);
--
1.7.10.4
^ permalink raw reply related [flat|nested] 37+ messages in thread
* [PATCH 18/22] staging:iio:ad7793: Use common Sigma Delta library
2012-08-10 16:36 [PATCH 01/22] staging:iio:ad7793: Add missing break in switch statement Lars-Peter Clausen
` (15 preceding siblings ...)
2012-08-10 16:36 ` [PATCH 17/22] staging:iio:ad7780: Use common Sigma Delta library Lars-Peter Clausen
@ 2012-08-10 16:36 ` Lars-Peter Clausen
2012-08-10 16:36 ` [PATCH 19/22] staging:iio:ad7192: " Lars-Peter Clausen
` (3 subsequent siblings)
20 siblings, 0 replies; 37+ messages in thread
From: Lars-Peter Clausen @ 2012-08-10 16:36 UTC (permalink / raw)
To: Jonathan Cameron; +Cc: linux-iio, drivers, Lars-Peter Clausen
Convert the ad7793 driver to make use of the new common code for devices from
the Analog Devices Sigma Delta family.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
---
drivers/staging/iio/adc/Kconfig | 3 +-
drivers/staging/iio/adc/ad7793.c | 625 +++++---------------------------------
drivers/staging/iio/adc/ad7793.h | 2 +
3 files changed, 75 insertions(+), 555 deletions(-)
diff --git a/drivers/staging/iio/adc/Kconfig b/drivers/staging/iio/adc/Kconfig
index fc7b7f6..05dea3f 100644
--- a/drivers/staging/iio/adc/Kconfig
+++ b/drivers/staging/iio/adc/Kconfig
@@ -111,8 +111,7 @@ config AD7780
config AD7793
tristate "Analog Devices AD7792 AD7793 ADC driver"
depends on SPI
- select IIO_BUFFER
- select IIO_TRIGGERED_BUFFER
+ select AD_SIGMA_DELTA
help
Say yes here to build support for Analog Devices
AD7792 and AD7793 SPI analog to digital converters (ADC).
diff --git a/drivers/staging/iio/adc/ad7793.c b/drivers/staging/iio/adc/ad7793.c
index 0ba598e..ba199fa 100644
--- a/drivers/staging/iio/adc/ad7793.c
+++ b/drivers/staging/iio/adc/ad7793.c
@@ -24,6 +24,7 @@
#include <linux/iio/trigger.h>
#include <linux/iio/trigger_consumer.h>
#include <linux/iio/triggered_buffer.h>
+#include <linux/iio/adc/ad_sigma_delta.h>
#include "ad7793.h"
@@ -36,27 +37,19 @@
*/
struct ad7793_chip_info {
- struct iio_chan_spec channel[7];
+ struct iio_chan_spec channel[7];
};
struct ad7793_state {
- struct spi_device *spi;
- struct iio_trigger *trig;
const struct ad7793_chip_info *chip_info;
struct regulator *reg;
- wait_queue_head_t wq_data_avail;
- bool done;
- bool irq_dis;
u16 int_vref_mv;
u16 mode;
u16 conf;
u32 scale_avail[8][2];
- /*
- * DMA (thus cache coherency maintenance) requires the
- * transfer buffers to live in their own cache lines.
- */
- u8 data[4] ____cacheline_aligned;
+ struct ad_sigma_delta sd;
+
};
enum ad7793_supported_device_ids {
@@ -64,169 +57,40 @@ enum ad7793_supported_device_ids {
ID_AD7793,
};
-static int __ad7793_write_reg(struct ad7793_state *st, bool locked,
- bool cs_change, unsigned char reg,
- unsigned size, unsigned val)
+static struct ad7793_state *ad_sigma_delta_to_ad7793(struct ad_sigma_delta *sd)
{
- u8 *data = st->data;
- struct spi_transfer t = {
- .tx_buf = data,
- .len = size + 1,
- .cs_change = cs_change,
- };
- struct spi_message m;
-
- data[0] = AD7793_COMM_WRITE | AD7793_COMM_ADDR(reg);
-
- switch (size) {
- case 3:
- data[1] = val >> 16;
- data[2] = val >> 8;
- data[3] = val;
- break;
- case 2:
- data[1] = val >> 8;
- data[2] = val;
- break;
- case 1:
- data[1] = val;
- break;
- default:
- return -EINVAL;
- }
-
- spi_message_init(&m);
- spi_message_add_tail(&t, &m);
-
- if (locked)
- return spi_sync_locked(st->spi, &m);
- else
- return spi_sync(st->spi, &m);
+ return container_of(sd, struct ad7793_state, sd);
}
-static int ad7793_write_reg(struct ad7793_state *st,
- unsigned reg, unsigned size, unsigned val)
+static int ad7793_set_channel(struct ad_sigma_delta *sd, unsigned int channel)
{
- return __ad7793_write_reg(st, false, false, reg, size, val);
-}
+ struct ad7793_state *st = ad_sigma_delta_to_ad7793(sd);
-static int __ad7793_read_reg(struct ad7793_state *st, bool locked,
- bool cs_change, unsigned char reg,
- int *val, unsigned size)
-{
- u8 *data = st->data;
- int ret;
- struct spi_transfer t[] = {
- {
- .tx_buf = data,
- .len = 1,
- }, {
- .rx_buf = data,
- .len = size,
- .cs_change = cs_change,
- },
- };
- struct spi_message m;
-
- data[0] = AD7793_COMM_READ | AD7793_COMM_ADDR(reg);
-
- spi_message_init(&m);
- spi_message_add_tail(&t[0], &m);
- spi_message_add_tail(&t[1], &m);
-
- if (locked)
- ret = spi_sync_locked(st->spi, &m);
- else
- ret = spi_sync(st->spi, &m);
+ st->conf &= ~AD7793_CONF_CHAN_MASK;
+ st->conf |= AD7793_CONF_CHAN(channel);
- if (ret < 0)
- return ret;
-
- switch (size) {
- case 3:
- *val = data[0] << 16 | data[1] << 8 | data[2];
- break;
- case 2:
- *val = data[0] << 8 | data[1];
- break;
- case 1:
- *val = data[0];
- break;
- default:
- return -EINVAL;
- }
-
- return 0;
+ return ad_sd_write_reg(&st->sd, AD7793_REG_CONF, 2, st->conf);
}
-static int ad7793_read_reg(struct ad7793_state *st,
- unsigned reg, int *val, unsigned size)
+static int ad7793_set_mode(struct ad_sigma_delta *sd, unsigned int mode)
{
- return __ad7793_read_reg(st, 0, 0, reg, val, size);
-}
-
-static int ad7793_read(struct ad7793_state *st, unsigned ch,
- unsigned len, int *val)
-{
- int ret;
- st->conf = (st->conf & ~AD7793_CONF_CHAN(-1)) | AD7793_CONF_CHAN(ch);
- st->mode = (st->mode & ~AD7793_MODE_SEL(-1)) |
- AD7793_MODE_SEL(AD7793_MODE_SINGLE);
+ struct ad7793_state *st = ad_sigma_delta_to_ad7793(sd);
- ad7793_write_reg(st, AD7793_REG_CONF, sizeof(st->conf), st->conf);
+ st->mode &= ~AD7793_MODE_SEL_MASK;
+ st->mode |= AD7793_MODE_SEL(mode);
- spi_bus_lock(st->spi->master);
- st->done = false;
-
- ret = __ad7793_write_reg(st, 1, 1, AD7793_REG_MODE,
- sizeof(st->mode), st->mode);
- if (ret < 0)
- goto out;
-
- st->irq_dis = false;
- enable_irq(st->spi->irq);
- wait_event_interruptible(st->wq_data_avail, st->done);
-
- ret = __ad7793_read_reg(st, 1, 0, AD7793_REG_DATA, val, len);
-out:
- spi_bus_unlock(st->spi->master);
-
- return ret;
+ return ad_sd_write_reg(&st->sd, AD7793_REG_MODE, 2, st->mode);
}
-static int ad7793_calibrate(struct ad7793_state *st, unsigned mode, unsigned ch)
-{
- int ret;
-
- st->conf = (st->conf & ~AD7793_CONF_CHAN(-1)) | AD7793_CONF_CHAN(ch);
- st->mode = (st->mode & ~AD7793_MODE_SEL(-1)) | AD7793_MODE_SEL(mode);
-
- ad7793_write_reg(st, AD7793_REG_CONF, sizeof(st->conf), st->conf);
-
- spi_bus_lock(st->spi->master);
- st->done = false;
-
- ret = __ad7793_write_reg(st, 1, 1, AD7793_REG_MODE,
- sizeof(st->mode), st->mode);
- if (ret < 0)
- goto out;
-
- st->irq_dis = false;
- enable_irq(st->spi->irq);
- wait_event_interruptible(st->wq_data_avail, st->done);
-
- st->mode = (st->mode & ~AD7793_MODE_SEL(-1)) |
- AD7793_MODE_SEL(AD7793_MODE_IDLE);
-
- ret = __ad7793_write_reg(st, 1, 0, AD7793_REG_MODE,
- sizeof(st->mode), st->mode);
-out:
- spi_bus_unlock(st->spi->master);
-
- return ret;
-}
+static const struct ad_sigma_delta_info ad7793_sigma_delta_info = {
+ .set_channel = ad7793_set_channel,
+ .set_mode = ad7793_set_mode,
+ .has_registers = true,
+ .addr_shift = 3,
+ .read_mask = BIT(6),
+};
-static const u8 ad7793_calib_arr[6][2] = {
+static const struct ad_sd_calib_data ad7793_calib_arr[6] = {
{AD7793_MODE_CAL_INT_ZERO, AD7793_CH_AIN1P_AIN1M},
{AD7793_MODE_CAL_INT_FULL, AD7793_CH_AIN1P_AIN1M},
{AD7793_MODE_CAL_INT_ZERO, AD7793_CH_AIN2P_AIN2M},
@@ -237,60 +101,49 @@ static const u8 ad7793_calib_arr[6][2] = {
static int ad7793_calibrate_all(struct ad7793_state *st)
{
- int i, ret;
-
- for (i = 0; i < ARRAY_SIZE(ad7793_calib_arr); i++) {
- ret = ad7793_calibrate(st, ad7793_calib_arr[i][0],
- ad7793_calib_arr[i][1]);
- if (ret)
- goto out;
- }
-
- return 0;
-out:
- dev_err(&st->spi->dev, "Calibration failed\n");
- return ret;
+ return ad_sd_calibrate_all(&st->sd, ad7793_calib_arr,
+ ARRAY_SIZE(ad7793_calib_arr));
}
-static int ad7793_setup(struct ad7793_state *st
+static int ad7793_setup(struct iio_dev *indio_dev,
const struct ad7793_platform_data *pdata)
{
+ struct ad7793_state *st = iio_priv(indio_dev);
int i, ret = -1;
unsigned long long scale_uv;
u32 id;
/* reset the serial interface */
- ret = spi_write(st->spi, (u8 *)&ret, sizeof(ret));
+ ret = spi_write(st->sd.spi, (u8 *)&ret, sizeof(ret));
if (ret < 0)
goto out;
msleep(1); /* Wait for at least 500us */
/* write/read test for device presence */
- ret = ad7793_read_reg(st, AD7793_REG_ID, &id, 1);
+ ret = ad_sd_read_reg(&st->sd, AD7793_REG_ID, 1, &id);
if (ret)
goto out;
id &= AD7793_ID_MASK;
if (!((id == AD7792_ID) || (id == AD7793_ID))) {
- dev_err(&st->spi->dev, "device ID query failed\n");
+ dev_err(&st->sd.spi->dev, "device ID query failed\n");
goto out;
}
- st->mode = (pdata->mode & ~AD7793_MODE_SEL(-1)) |
- AD7793_MODE_SEL(AD7793_MODE_IDLE);
- st->conf = pdata->conf & ~AD7793_CONF_CHAN(-1);
+ st->mode = pdata->mode;
+ st->conf = pdata->conf;
- ret = ad7793_write_reg(st, AD7793_REG_MODE, sizeof(st->mode), st->mode);
+ ret = ad7793_set_mode(&st->sd, AD_SD_MODE_IDLE);
if (ret)
goto out;
- ret = ad7793_write_reg(st, AD7793_REG_CONF, sizeof(st->conf), st->conf);
+ ret = ad7793_set_channel(&st->sd, 0);
if (ret)
goto out;
- ret = ad7793_write_reg(st, AD7793_REG_IO,
- sizeof(st->pdata->io), st->pdata->io);
+ ret = ad_sd_write_reg(&st->sd, AD7793_REG_IO,
+ sizeof(pdata->io), pdata->io);
if (ret)
goto out;
@@ -311,184 +164,10 @@ static int ad7793_setup(struct ad7793_state *st
return 0;
out:
- dev_err(&st->spi->dev, "setup failed\n");
- return ret;
-}
-
-static int ad7793_ring_preenable(struct iio_dev *indio_dev)
-{
- struct ad7793_state *st = iio_priv(indio_dev);
- unsigned channel;
- int ret;
-
- if (bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength))
- return -EINVAL;
- ret = iio_sw_buffer_preenable(indio_dev);
- if (ret < 0)
- return ret;
-
- channel = find_first_bit(indio_dev->active_scan_mask,
- indio_dev->masklength);
-
- st->mode = (st->mode & ~AD7793_MODE_SEL(-1)) |
- AD7793_MODE_SEL(AD7793_MODE_CONT);
- st->conf = (st->conf & ~AD7793_CONF_CHAN(-1)) |
- AD7793_CONF_CHAN(indio_dev->channels[channel].address);
-
- ad7793_write_reg(st, AD7793_REG_CONF, sizeof(st->conf), st->conf);
-
- spi_bus_lock(st->spi->master);
- __ad7793_write_reg(st, 1, 1, AD7793_REG_MODE,
- sizeof(st->mode), st->mode);
-
- st->irq_dis = false;
- enable_irq(st->spi->irq);
-
- return 0;
-}
-
-static int ad7793_ring_postdisable(struct iio_dev *indio_dev)
-{
- struct ad7793_state *st = iio_priv(indio_dev);
-
- st->mode = (st->mode & ~AD7793_MODE_SEL(-1)) |
- AD7793_MODE_SEL(AD7793_MODE_IDLE);
-
- st->done = false;
- wait_event_interruptible(st->wq_data_avail, st->done);
-
- if (!st->irq_dis)
- disable_irq_nosync(st->spi->irq);
-
- __ad7793_write_reg(st, 1, 0, AD7793_REG_MODE,
- sizeof(st->mode), st->mode);
-
- return spi_bus_unlock(st->spi->master);
-}
-
-/**
- * ad7793_trigger_handler() bh of trigger launched polling to ring buffer
- **/
-
-static irqreturn_t ad7793_trigger_handler(int irq, void *p)
-{
- struct iio_poll_func *pf = p;
- struct iio_dev *indio_dev = pf->indio_dev;
- struct iio_buffer *ring = indio_dev->buffer;
- struct ad7793_state *st = iio_priv(indio_dev);
- s64 dat64[2];
- s32 *dat32 = (s32 *)dat64;
-
- if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength))
- __ad7793_read_reg(st, 1, 1, AD7793_REG_DATA,
- dat32,
- indio_dev->channels[0].scan_type.realbits/8);
-
- /* Guaranteed to be aligned with 8 byte boundary */
- if (indio_dev->scan_timestamp)
- dat64[1] = pf->timestamp;
-
- ring->access->store_to(ring, (u8 *)dat64, pf->timestamp);
-
- iio_trigger_notify_done(indio_dev->trig);
- st->irq_dis = false;
- enable_irq(st->spi->irq);
-
- return IRQ_HANDLED;
-}
-
-static const struct iio_buffer_setup_ops ad7793_ring_setup_ops = {
- .preenable = &ad7793_ring_preenable,
- .postenable = &iio_triggered_buffer_postenable,
- .predisable = &iio_triggered_buffer_predisable,
- .postdisable = &ad7793_ring_postdisable,
- .validate_scan_mask = &iio_validate_scan_mask_onehot,
-};
-
-static int ad7793_register_ring_funcs_and_init(struct iio_dev *indio_dev)
-{
- return iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,
- &ad7793_trigger_handler, &ad7793_ring_setup_ops);
-}
-
-static void ad7793_ring_cleanup(struct iio_dev *indio_dev)
-{
- iio_triggered_buffer_cleanup(indio_dev);
-}
-
-/**
- * ad7793_data_rdy_trig_poll() the event handler for the data rdy trig
- **/
-static irqreturn_t ad7793_data_rdy_trig_poll(int irq, void *private)
-{
- struct ad7793_state *st = iio_priv(private);
-
- st->done = true;
- wake_up_interruptible(&st->wq_data_avail);
- disable_irq_nosync(irq);
- st->irq_dis = true;
- iio_trigger_poll(st->trig, iio_get_time_ns());
-
- return IRQ_HANDLED;
-}
-
-static struct iio_trigger_ops ad7793_trigger_ops = {
- .owner = THIS_MODULE,
-};
-
-static int ad7793_probe_trigger(struct iio_dev *indio_dev)
-{
- struct ad7793_state *st = iio_priv(indio_dev);
- int ret;
-
- st->trig = iio_trigger_alloc("%s-dev%d",
- spi_get_device_id(st->spi)->name,
- indio_dev->id);
- if (st->trig == NULL) {
- ret = -ENOMEM;
- goto error_ret;
- }
- st->trig->ops = &ad7793_trigger_ops;
-
- ret = request_irq(st->spi->irq,
- ad7793_data_rdy_trig_poll,
- IRQF_TRIGGER_LOW,
- spi_get_device_id(st->spi)->name,
- indio_dev);
- if (ret)
- goto error_free_trig;
-
- disable_irq_nosync(st->spi->irq);
- st->irq_dis = true;
- st->trig->dev.parent = &st->spi->dev;
- st->trig->private_data = indio_dev;
-
- ret = iio_trigger_register(st->trig);
-
- /* select default trigger */
- indio_dev->trig = st->trig;
- if (ret)
- goto error_free_irq;
-
- return 0;
-
-error_free_irq:
- free_irq(st->spi->irq, indio_dev);
-error_free_trig:
- iio_trigger_free(st->trig);
-error_ret:
+ dev_err(&st->sd.spi->dev, "setup failed\n");
return ret;
}
-static void ad7793_remove_trigger(struct iio_dev *indio_dev)
-{
- struct ad7793_state *st = iio_priv(indio_dev);
-
- iio_trigger_unregister(st->trig);
- free_irq(st->spi->irq, indio_dev);
- iio_trigger_free(st->trig);
-}
-
static const u16 sample_freq_avail[16] = {0, 470, 242, 123, 62, 50, 39, 33, 19,
17, 16, 12, 10, 8, 6, 4};
@@ -531,7 +210,7 @@ static ssize_t ad7793_write_frequency(struct device *dev,
mutex_lock(&indio_dev->mlock);
st->mode &= ~AD7793_MODE_RATE(-1);
st->mode |= AD7793_MODE_RATE(i);
- ad7793_write_reg(st, AD7793_REG_MODE,
+ ad_sd_write_reg(&st->sd, AD7793_REG_MODE,
sizeof(st->mode), st->mode);
mutex_unlock(&indio_dev->mlock);
ret = 0;
@@ -585,26 +264,16 @@ static int ad7793_read_raw(struct iio_dev *indio_dev,
long m)
{
struct ad7793_state *st = iio_priv(indio_dev);
- int ret, smpl = 0;
+ int ret;
unsigned long long scale_uv;
bool unipolar = !!(st->conf & AD7793_CONF_UNIPOLAR);
switch (m) {
case IIO_CHAN_INFO_RAW:
- mutex_lock(&indio_dev->mlock);
- if (iio_buffer_enabled(indio_dev))
- ret = -EBUSY;
- else
- ret = ad7793_read(st, chan->address,
- chan->scan_type.realbits / 8, &smpl);
- mutex_unlock(&indio_dev->mlock);
-
+ ret = ad_sigma_delta_single_conversion(indio_dev, chan, val);
if (ret < 0)
return ret;
- *val = (smpl >> chan->scan_type.shift) &
- ((1 << (chan->scan_type.realbits)) - 1);
-
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
@@ -675,17 +344,18 @@ static int ad7793_write_raw(struct iio_dev *indio_dev,
ret = -EINVAL;
for (i = 0; i < ARRAY_SIZE(st->scale_avail); i++)
if (val2 == st->scale_avail[i][1]) {
+ ret = 0;
tmp = st->conf;
st->conf &= ~AD7793_CONF_GAIN(-1);
st->conf |= AD7793_CONF_GAIN(i);
- if (tmp != st->conf) {
- ad7793_write_reg(st, AD7793_REG_CONF,
- sizeof(st->conf),
- st->conf);
- ad7793_calibrate_all(st);
- }
- ret = 0;
+ if (tmp == st->conf)
+ break;
+
+ ad_sd_write_reg(&st->sd, AD7793_REG_CONF,
+ sizeof(st->conf), st->conf);
+ ad7793_calibrate_all(st);
+ break;
}
break;
default:
@@ -696,15 +366,6 @@ static int ad7793_write_raw(struct iio_dev *indio_dev,
return ret;
}
-static int ad7793_validate_trigger(struct iio_dev *indio_dev,
- struct iio_trigger *trig)
-{
- if (indio_dev->trig != trig)
- return -EINVAL;
-
- return 0;
-}
-
static int ad7793_write_raw_get_fmt(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
long mask)
@@ -717,166 +378,32 @@ static const struct iio_info ad7793_info = {
.write_raw = &ad7793_write_raw,
.write_raw_get_fmt = &ad7793_write_raw_get_fmt,
.attrs = &ad7793_attribute_group,
- .validate_trigger = ad7793_validate_trigger,
+ .validate_trigger = ad_sd_validate_trigger,
.driver_module = THIS_MODULE,
};
static const struct ad7793_chip_info ad7793_chip_info_tbl[] = {
[ID_AD7793] = {
- .channel[0] = {
- .type = IIO_VOLTAGE,
- .differential = 1,
- .indexed = 1,
- .channel = 0,
- .channel2 = 0,
- .address = AD7793_CH_AIN1P_AIN1M,
- .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
- IIO_CHAN_INFO_SCALE_SHARED_BIT |
- IIO_CHAN_INFO_OFFSET_SHARED_BIT,
- .scan_index = 0,
- .scan_type = IIO_ST('u', 24, 32, 0)
- },
- .channel[1] = {
- .type = IIO_VOLTAGE,
- .differential = 1,
- .indexed = 1,
- .channel = 1,
- .channel2 = 1,
- .address = AD7793_CH_AIN2P_AIN2M,
- .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
- IIO_CHAN_INFO_SCALE_SHARED_BIT |
- IIO_CHAN_INFO_OFFSET_SHARED_BIT,
- .scan_index = 1,
- .scan_type = IIO_ST('u', 24, 32, 0)
- },
- .channel[2] = {
- .type = IIO_VOLTAGE,
- .differential = 1,
- .indexed = 1,
- .channel = 2,
- .channel2 = 2,
- .address = AD7793_CH_AIN3P_AIN3M,
- .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
- IIO_CHAN_INFO_SCALE_SHARED_BIT |
- IIO_CHAN_INFO_OFFSET_SHARED_BIT,
- .scan_index = 2,
- .scan_type = IIO_ST('u', 24, 32, 0)
- },
- .channel[3] = {
- .type = IIO_VOLTAGE,
- .differential = 1,
- .extend_name = "shorted",
- .indexed = 1,
- .channel = 2,
- .channel2 = 2,
- .address = AD7793_CH_AIN1M_AIN1M,
- .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
- IIO_CHAN_INFO_SCALE_SHARED_BIT |
- IIO_CHAN_INFO_OFFSET_SHARED_BIT,
- .scan_index = 3,
- .scan_type = IIO_ST('u', 24, 32, 0)
- },
- .channel[4] = {
- .type = IIO_TEMP,
- .indexed = 1,
- .channel = 0,
- .address = AD7793_CH_TEMP,
- .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
- IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
- .scan_index = 4,
- .scan_type = IIO_ST('u', 24, 32, 0),
+ .channel = {
+ AD_SD_DIFF_CHANNEL(0, 0, 0, AD7793_CH_AIN1P_AIN1M, 24, 32, 0),
+ AD_SD_DIFF_CHANNEL(1, 1, 1, AD7793_CH_AIN2P_AIN2M, 24, 32, 0),
+ AD_SD_DIFF_CHANNEL(2, 2, 2, AD7793_CH_AIN3P_AIN3M, 24, 32, 0),
+ AD_SD_SHORTED_CHANNEL(3, 0, AD7793_CH_AIN1M_AIN1M, 24, 32, 0),
+ AD_SD_TEMP_CHANNEL(4, AD7793_CH_TEMP, 24, 32, 0),
+ AD_SD_SUPPLY_CHANNEL(5, 3, AD7793_CH_AVDD_MONITOR, 24, 32, 0),
+ IIO_CHAN_SOFT_TIMESTAMP(6),
},
- .channel[5] = {
- .type = IIO_VOLTAGE,
- .extend_name = "supply",
- .indexed = 1,
- .channel = 4,
- .address = AD7793_CH_AVDD_MONITOR,
- .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
- IIO_CHAN_INFO_SCALE_SEPARATE_BIT |
- IIO_CHAN_INFO_OFFSET_SHARED_BIT,
- .scan_index = 5,
- .scan_type = IIO_ST('u', 24, 32, 0),
- },
- .channel[6] = IIO_CHAN_SOFT_TIMESTAMP(6),
},
[ID_AD7792] = {
- .channel[0] = {
- .type = IIO_VOLTAGE,
- .differential = 1,
- .indexed = 1,
- .channel = 0,
- .channel2 = 0,
- .address = AD7793_CH_AIN1P_AIN1M,
- .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
- IIO_CHAN_INFO_SCALE_SHARED_BIT |
- IIO_CHAN_INFO_OFFSET_SHARED_BIT,
- .scan_index = 0,
- .scan_type = IIO_ST('u', 16, 32, 0)
- },
- .channel[1] = {
- .type = IIO_VOLTAGE,
- .differential = 1,
- .indexed = 1,
- .channel = 1,
- .channel2 = 1,
- .address = AD7793_CH_AIN2P_AIN2M,
- .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
- IIO_CHAN_INFO_SCALE_SHARED_BIT |
- IIO_CHAN_INFO_OFFSET_SHARED_BIT,
- .scan_index = 1,
- .scan_type = IIO_ST('u', 16, 32, 0)
- },
- .channel[2] = {
- .type = IIO_VOLTAGE,
- .differential = 1,
- .indexed = 1,
- .channel = 2,
- .channel2 = 2,
- .address = AD7793_CH_AIN3P_AIN3M,
- .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
- IIO_CHAN_INFO_SCALE_SHARED_BIT |
- IIO_CHAN_INFO_OFFSET_SHARED_BIT,
- .scan_index = 2,
- .scan_type = IIO_ST('u', 16, 32, 0)
- },
- .channel[3] = {
- .type = IIO_VOLTAGE,
- .differential = 1,
- .extend_name = "shorted",
- .indexed = 1,
- .channel = 2,
- .channel2 = 2,
- .address = AD7793_CH_AIN1M_AIN1M,
- .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
- IIO_CHAN_INFO_SCALE_SHARED_BIT |
- IIO_CHAN_INFO_OFFSET_SHARED_BIT,
- .scan_index = 3,
- .scan_type = IIO_ST('u', 16, 32, 0)
- },
- .channel[4] = {
- .type = IIO_TEMP,
- .indexed = 1,
- .channel = 0,
- .address = AD7793_CH_TEMP,
- .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
- IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
- .scan_index = 4,
- .scan_type = IIO_ST('u', 16, 32, 0),
+ .channel = {
+ AD_SD_DIFF_CHANNEL(0, 0, 0, AD7793_CH_AIN1P_AIN1M, 16, 32, 0),
+ AD_SD_DIFF_CHANNEL(1, 1, 1, AD7793_CH_AIN2P_AIN2M, 16, 32, 0),
+ AD_SD_DIFF_CHANNEL(2, 2, 2, AD7793_CH_AIN3P_AIN3M, 16, 32, 0),
+ AD_SD_SHORTED_CHANNEL(3, 0, AD7793_CH_AIN1M_AIN1M, 16, 32, 0),
+ AD_SD_TEMP_CHANNEL(4, AD7793_CH_TEMP, 16, 32, 0),
+ AD_SD_SUPPLY_CHANNEL(5, 3, AD7793_CH_AVDD_MONITOR, 16, 32, 0),
+ IIO_CHAN_SOFT_TIMESTAMP(6),
},
- .channel[5] = {
- .type = IIO_VOLTAGE,
- .extend_name = "supply",
- .indexed = 1,
- .channel = 4,
- .address = AD7793_CH_AVDD_MONITOR,
- .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
- IIO_CHAN_INFO_SCALE_SEPARATE_BIT |
- IIO_CHAN_INFO_OFFSET_SHARED_BIT,
- .scan_index = 5,
- .scan_type = IIO_ST('u', 16, 32, 0),
- },
- .channel[6] = IIO_CHAN_SOFT_TIMESTAMP(6),
},
};
@@ -903,6 +430,8 @@ static int __devinit ad7793_probe(struct spi_device *spi)
st = iio_priv(indio_dev);
+ ad_sd_init(&st->sd, indio_dev, spi, &ad7793_sigma_delta_info);
+
st->reg = regulator_get(&spi->dev, "vcc");
if (!IS_ERR(st->reg)) {
ret = regulator_enable(st->reg);
@@ -923,7 +452,6 @@ static int __devinit ad7793_probe(struct spi_device *spi)
st->int_vref_mv = 1170; /* Build-in ref */
spi_set_drvdata(spi, indio_dev);
- st->spi = spi;
indio_dev->dev.parent = &spi->dev;
indio_dev->name = spi_get_device_id(spi)->name;
@@ -932,17 +460,11 @@ static int __devinit ad7793_probe(struct spi_device *spi)
indio_dev->num_channels = 7;
indio_dev->info = &ad7793_info;
- init_waitqueue_head(&st->wq_data_avail);
-
- ret = ad7793_register_ring_funcs_and_init(indio_dev);
+ ret = ad_sd_setup_buffer_and_trigger(indio_dev);
if (ret)
goto error_disable_reg;
- ret = ad7793_probe_trigger(indio_dev);
- if (ret)
- goto error_unreg_ring;
-
- ret = ad7793_setup(st, pdata);
+ ret = ad7793_setup(indio_dev, pdata);
if (ret)
goto error_remove_trigger;
@@ -953,9 +475,7 @@ static int __devinit ad7793_probe(struct spi_device *spi)
return 0;
error_remove_trigger:
- ad7793_remove_trigger(indio_dev);
-error_unreg_ring:
- ad7793_ring_cleanup(indio_dev);
+ ad_sd_cleanup_buffer_and_trigger(indio_dev);
error_disable_reg:
if (!IS_ERR(st->reg))
regulator_disable(st->reg);
@@ -974,8 +494,7 @@ static int ad7793_remove(struct spi_device *spi)
struct ad7793_state *st = iio_priv(indio_dev);
iio_device_unregister(indio_dev);
- ad7793_remove_trigger(indio_dev);
- ad7793_ring_cleanup(indio_dev);
+ ad_sd_cleanup_buffer_and_trigger(indio_dev);
if (!IS_ERR(st->reg)) {
regulator_disable(st->reg);
diff --git a/drivers/staging/iio/adc/ad7793.h b/drivers/staging/iio/adc/ad7793.h
index 64f7d41..0e296d8 100644
--- a/drivers/staging/iio/adc/ad7793.h
+++ b/drivers/staging/iio/adc/ad7793.h
@@ -41,6 +41,7 @@
/* Mode Register Bit Designations (AD7793_REG_MODE) */
#define AD7793_MODE_SEL(x) (((x) & 0x7) << 13) /* Operation Mode Select */
+#define AD7793_MODE_SEL_MASK (0x7 << 13) /* Operation Mode Select mask */
#define AD7793_MODE_CLKSRC(x) (((x) & 0x3) << 6) /* ADC Clock Source Select */
#define AD7793_MODE_RATE(x) ((x) & 0xF) /* Filter Update Rate Select */
@@ -70,6 +71,7 @@
#define AD7793_CONF_REFSEL (1 << 7) /* INT/EXT Reference Select */
#define AD7793_CONF_BUF (1 << 4) /* Buffered Mode Enable */
#define AD7793_CONF_CHAN(x) ((x) & 0x7) /* Channel select */
+#define AD7793_CONF_CHAN_MASK 0x7 /* Channel select mask */
#define AD7793_CH_AIN1P_AIN1M 0 /* AIN1(+) - AIN1(-) */
#define AD7793_CH_AIN2P_AIN2M 1 /* AIN2(+) - AIN2(-) */
--
1.7.10.4
^ permalink raw reply related [flat|nested] 37+ messages in thread
* [PATCH 19/22] staging:iio:ad7192: Use common Sigma Delta library
2012-08-10 16:36 [PATCH 01/22] staging:iio:ad7793: Add missing break in switch statement Lars-Peter Clausen
` (16 preceding siblings ...)
2012-08-10 16:36 ` [PATCH 18/22] staging:iio:ad7793: " Lars-Peter Clausen
@ 2012-08-10 16:36 ` Lars-Peter Clausen
2012-08-27 17:07 ` Jonathan Cameron
2012-08-10 16:36 ` [PATCH 20/22] staging:iio:ad7793: Add support for ad7794/ad7795 Lars-Peter Clausen
` (2 subsequent siblings)
20 siblings, 1 reply; 37+ messages in thread
From: Lars-Peter Clausen @ 2012-08-10 16:36 UTC (permalink / raw)
To: Jonathan Cameron; +Cc: linux-iio, drivers, Lars-Peter Clausen
Convert the ad7192 driver to make use of the new common code for devices from
the Analog Devices Sigma Delta family.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
---
drivers/staging/iio/adc/Kconfig | 3 +-
drivers/staging/iio/adc/ad7192.c | 507 +++++---------------------------------
2 files changed, 61 insertions(+), 449 deletions(-)
diff --git a/drivers/staging/iio/adc/Kconfig b/drivers/staging/iio/adc/Kconfig
index 05dea3f..9525308 100644
--- a/drivers/staging/iio/adc/Kconfig
+++ b/drivers/staging/iio/adc/Kconfig
@@ -131,8 +131,7 @@ config AD7816
config AD7192
tristate "Analog Devices AD7190 AD7192 AD7195 ADC driver"
depends on SPI
- select IIO_BUFFER
- select IIO_TRIGGERED_BUFFER
+ select AD_SIGMA_DELTA
help
Say yes here to build support for Analog Devices AD7190,
AD7192 or AD7195 SPI analog to digital converters (ADC).
diff --git a/drivers/staging/iio/adc/ad7192.c b/drivers/staging/iio/adc/ad7192.c
index cdb4fc4..34a7dee 100644
--- a/drivers/staging/iio/adc/ad7192.c
+++ b/drivers/staging/iio/adc/ad7192.c
@@ -23,6 +23,7 @@
#include <linux/iio/trigger.h>
#include <linux/iio/trigger_consumer.h>
#include <linux/iio/triggered_buffer.h>
+#include <linux/iio/adc/ad_sigma_delta.h>
#include "ad7192.h"
@@ -57,6 +58,7 @@
/* Mode Register Bit Designations (AD7192_REG_MODE) */
#define AD7192_MODE_SEL(x) (((x) & 0x7) << 21) /* Operation Mode Select */
+#define AD7192_MODE_SEL_MASK (0x7 << 21) /* Operation Mode Select Mask */
#define AD7192_MODE_DAT_STA (1 << 20) /* Status Register transmission */
#define AD7192_MODE_CLKSRC(x) (((x) & 0x3) << 18) /* Clock Source Select */
#define AD7192_MODE_SINC3 (1 << 15) /* SINC3 Filter Select */
@@ -91,7 +93,8 @@
#define AD7192_CONF_CHOP (1 << 23) /* CHOP enable */
#define AD7192_CONF_REFSEL (1 << 20) /* REFIN1/REFIN2 Reference Select */
-#define AD7192_CONF_CHAN(x) (((x) & 0xFF) << 8) /* Channel select */
+#define AD7192_CONF_CHAN(x) (((1 << (x)) & 0xFF) << 8) /* Channel select */
+#define AD7192_CONF_CHAN_MASK (0xFF << 8) /* Channel select mask */
#define AD7192_CONF_BURN (1 << 7) /* Burnout current enable */
#define AD7192_CONF_REFDET (1 << 6) /* Reference detect enable */
#define AD7192_CONF_BUF (1 << 4) /* Buffered Mode Enable */
@@ -133,12 +136,7 @@
*/
struct ad7192_state {
- struct spi_device *spi;
- struct iio_trigger *trig;
struct regulator *reg;
- wait_queue_head_t wq_data_avail;
- bool done;
- bool irq_dis;
u16 int_vref_mv;
u32 mclk;
u32 f_order;
@@ -147,178 +145,44 @@ struct ad7192_state {
u32 scale_avail[8][2];
u8 gpocon;
u8 devid;
- /*
- * DMA (thus cache coherency maintenance) requires the
- * transfer buffers to live in their own cache lines.
- */
- u8 data[4] ____cacheline_aligned;
-};
-
-static int __ad7192_write_reg(struct ad7192_state *st, bool locked,
- bool cs_change, unsigned char reg,
- unsigned size, unsigned val)
-{
- u8 *data = st->data;
- struct spi_transfer t = {
- .tx_buf = data,
- .len = size + 1,
- .cs_change = cs_change,
- };
- struct spi_message m;
-
- data[0] = AD7192_COMM_WRITE | AD7192_COMM_ADDR(reg);
-
- switch (size) {
- case 3:
- data[1] = val >> 16;
- data[2] = val >> 8;
- data[3] = val;
- break;
- case 2:
- data[1] = val >> 8;
- data[2] = val;
- break;
- case 1:
- data[1] = val;
- break;
- default:
- return -EINVAL;
- }
- spi_message_init(&m);
- spi_message_add_tail(&t, &m);
-
- if (locked)
- return spi_sync_locked(st->spi, &m);
- else
- return spi_sync(st->spi, &m);
-}
+ struct ad_sigma_delta sd;
+};
-static int ad7192_write_reg(struct ad7192_state *st,
- unsigned reg, unsigned size, unsigned val)
+static struct ad7192_state *ad_sigma_delta_to_ad7192(struct ad_sigma_delta *sd)
{
- return __ad7192_write_reg(st, false, false, reg, size, val);
+ return container_of(sd, struct ad7192_state, sd);
}
-static int __ad7192_read_reg(struct ad7192_state *st, bool locked,
- bool cs_change, unsigned char reg,
- int *val, unsigned size)
+static int ad7192_set_channel(struct ad_sigma_delta *sd, unsigned int channel)
{
- u8 *data = st->data;
- int ret;
- struct spi_transfer t[] = {
- {
- .tx_buf = data,
- .len = 1,
- }, {
- .rx_buf = data,
- .len = size,
- .cs_change = cs_change,
- },
- };
- struct spi_message m;
-
- data[0] = AD7192_COMM_READ | AD7192_COMM_ADDR(reg);
-
- spi_message_init(&m);
- spi_message_add_tail(&t[0], &m);
- spi_message_add_tail(&t[1], &m);
-
- if (locked)
- ret = spi_sync_locked(st->spi, &m);
- else
- ret = spi_sync(st->spi, &m);
+ struct ad7192_state *st = ad_sigma_delta_to_ad7192(sd);
- if (ret < 0)
- return ret;
+ st->conf &= ~AD7192_CONF_CHAN_MASK;
+ st->conf |= AD7192_CONF_CHAN(channel);
- switch (size) {
- case 3:
- *val = data[0] << 16 | data[1] << 8 | data[2];
- break;
- case 2:
- *val = data[0] << 8 | data[1];
- break;
- case 1:
- *val = data[0];
- break;
- default:
- return -EINVAL;
- }
-
- return 0;
+ return ad_sd_write_reg(&st->sd, AD7192_REG_CONF, 3, st->conf);
}
-static int ad7192_read_reg(struct ad7192_state *st,
- unsigned reg, int *val, unsigned size)
+static int ad7192_set_mode(struct ad_sigma_delta *sd, unsigned int mode)
{
- return __ad7192_read_reg(st, 0, 0, reg, val, size);
-}
-
-static int ad7192_read(struct ad7192_state *st, unsigned ch,
- unsigned len, int *val)
-{
- int ret;
- st->conf = (st->conf & ~AD7192_CONF_CHAN(-1)) |
- AD7192_CONF_CHAN(1 << ch);
- st->mode = (st->mode & ~AD7192_MODE_SEL(-1)) |
- AD7192_MODE_SEL(AD7192_MODE_SINGLE);
-
- ad7192_write_reg(st, AD7192_REG_CONF, 3, st->conf);
+ struct ad7192_state *st = ad_sigma_delta_to_ad7192(sd);
- spi_bus_lock(st->spi->master);
- st->done = false;
+ st->mode &= ~AD7192_MODE_SEL_MASK;
+ st->mode |= AD7192_MODE_SEL(mode);
- ret = __ad7192_write_reg(st, 1, 1, AD7192_REG_MODE, 3, st->mode);
- if (ret < 0)
- goto out;
-
- st->irq_dis = false;
- enable_irq(st->spi->irq);
- wait_event_interruptible(st->wq_data_avail, st->done);
-
- ret = __ad7192_read_reg(st, 1, 0, AD7192_REG_DATA, val, len);
-out:
- spi_bus_unlock(st->spi->master);
-
- return ret;
+ return ad_sd_write_reg(&st->sd, AD7192_REG_MODE, 3, st->mode);
}
-static int ad7192_calibrate(struct ad7192_state *st, unsigned mode, unsigned ch)
-{
- int ret;
-
- st->conf = (st->conf & ~AD7192_CONF_CHAN(-1)) |
- AD7192_CONF_CHAN(1 << ch);
- st->mode = (st->mode & ~AD7192_MODE_SEL(-1)) | AD7192_MODE_SEL(mode);
-
- ad7192_write_reg(st, AD7192_REG_CONF, 3, st->conf);
-
- spi_bus_lock(st->spi->master);
- st->done = false;
-
- ret = __ad7192_write_reg(st, 1, 1, AD7192_REG_MODE, 3,
- (st->devid != ID_AD7195) ?
- st->mode | AD7192_MODE_CLKDIV :
- st->mode);
- if (ret < 0)
- goto out;
-
- st->irq_dis = false;
- enable_irq(st->spi->irq);
- wait_event_interruptible(st->wq_data_avail, st->done);
-
- st->mode = (st->mode & ~AD7192_MODE_SEL(-1)) |
- AD7192_MODE_SEL(AD7192_MODE_IDLE);
-
- ret = __ad7192_write_reg(st, 1, 0, AD7192_REG_MODE, 3, st->mode);
-out:
- spi_bus_unlock(st->spi->master);
-
- return ret;
-}
+static const struct ad_sigma_delta_info ad7192_sigma_delta_info = {
+ .set_channel = ad7192_set_channel,
+ .set_mode = ad7192_set_mode,
+ .has_registers = true,
+ .addr_shift = 3,
+ .read_mask = BIT(6),
+};
-static const u8 ad7192_calib_arr[8][2] = {
+static const struct ad_sd_calib_data ad7192_calib_arr[8] = {
{AD7192_MODE_CAL_INT_ZERO, AD7192_CH_AIN1},
{AD7192_MODE_CAL_INT_FULL, AD7192_CH_AIN1},
{AD7192_MODE_CAL_INT_ZERO, AD7192_CH_AIN2},
@@ -331,45 +195,34 @@ static const u8 ad7192_calib_arr[8][2] = {
static int ad7192_calibrate_all(struct ad7192_state *st)
{
- int i, ret;
-
- for (i = 0; i < ARRAY_SIZE(ad7192_calib_arr); i++) {
- ret = ad7192_calibrate(st, ad7192_calib_arr[i][0],
- ad7192_calib_arr[i][1]);
- if (ret)
- goto out;
- }
-
- return 0;
-out:
- dev_err(&st->spi->dev, "Calibration failed\n");
- return ret;
+ return ad_sd_calibrate_all(&st->sd, ad7192_calib_arr,
+ ARRAY_SIZE(ad7192_calib_arr));
}
static int ad7192_setup(struct ad7192_state *st,
const struct ad7192_platform_data *pdata)
{
- struct iio_dev *indio_dev = spi_get_drvdata(st->spi);
+ struct iio_dev *indio_dev = spi_get_drvdata(st->sd.spi);
unsigned long long scale_uv;
int i, ret, id;
u8 ones[6];
/* reset the serial interface */
memset(&ones, 0xFF, 6);
- ret = spi_write(st->spi, &ones, 6);
+ ret = spi_write(st->sd.spi, &ones, 6);
if (ret < 0)
goto out;
msleep(1); /* Wait for at least 500us */
/* write/read test for device presence */
- ret = ad7192_read_reg(st, AD7192_REG_ID, &id, 1);
+ ret = ad_sd_read_reg(&st->sd, AD7192_REG_ID, 1, &id);
if (ret)
goto out;
id &= AD7192_ID_MASK;
if (id != st->devid)
- dev_warn(&st->spi->dev, "device ID query failed (0x%X)\n", id);
+ dev_warn(&st->sd.spi->dev, "device ID query failed (0x%X)\n", id);
switch (pdata->clock_source_sel) {
case AD7192_CLK_EXT_MCLK1_2:
@@ -422,11 +275,11 @@ static int ad7192_setup(struct ad7192_state *st,
if (pdata->burnout_curr_en)
st->conf |= AD7192_CONF_BURN;
- ret = ad7192_write_reg(st, AD7192_REG_MODE, 3, st->mode);
+ ret = ad_sd_write_reg(&st->sd, AD7192_REG_MODE, 3, st->mode);
if (ret)
goto out;
- ret = ad7192_write_reg(st, AD7192_REG_CONF, 3, st->conf);
+ ret = ad_sd_write_reg(&st->sd, AD7192_REG_CONF, 3, st->conf);
if (ret)
goto out;
@@ -447,181 +300,10 @@ static int ad7192_setup(struct ad7192_state *st,
return 0;
out:
- dev_err(&st->spi->dev, "setup failed\n");
+ dev_err(&st->sd.spi->dev, "setup failed\n");
return ret;
}
-static int ad7192_ring_preenable(struct iio_dev *indio_dev)
-{
- struct ad7192_state *st = iio_priv(indio_dev);
- unsigned channel;
- int ret;
-
- if (bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength))
- return -EINVAL;
-
- ret = iio_sw_buffer_preenable(indio_dev);
- if (ret < 0)
- return ret;
-
- channel = find_first_bit(indio_dev->active_scan_mask,
- indio_dev->masklength);
-
- st->mode = (st->mode & ~AD7192_MODE_SEL(-1)) |
- AD7192_MODE_SEL(AD7192_MODE_CONT);
- st->conf = (st->conf & ~AD7192_CONF_CHAN(-1)) |
- AD7192_CONF_CHAN(1 << indio_dev->channels[channel].address);
-
- ad7192_write_reg(st, AD7192_REG_CONF, 3, st->conf);
-
- spi_bus_lock(st->spi->master);
- __ad7192_write_reg(st, 1, 1, AD7192_REG_MODE, 3, st->mode);
-
- st->irq_dis = false;
- enable_irq(st->spi->irq);
-
- return 0;
-}
-
-static int ad7192_ring_postdisable(struct iio_dev *indio_dev)
-{
- struct ad7192_state *st = iio_priv(indio_dev);
-
- st->mode = (st->mode & ~AD7192_MODE_SEL(-1)) |
- AD7192_MODE_SEL(AD7192_MODE_IDLE);
-
- st->done = false;
- wait_event_interruptible(st->wq_data_avail, st->done);
-
- if (!st->irq_dis)
- disable_irq_nosync(st->spi->irq);
-
- __ad7192_write_reg(st, 1, 0, AD7192_REG_MODE, 3, st->mode);
-
- return spi_bus_unlock(st->spi->master);
-}
-
-/**
- * ad7192_trigger_handler() bh of trigger launched polling to ring buffer
- **/
-static irqreturn_t ad7192_trigger_handler(int irq, void *p)
-{
- struct iio_poll_func *pf = p;
- struct iio_dev *indio_dev = pf->indio_dev;
- struct iio_buffer *ring = indio_dev->buffer;
- struct ad7192_state *st = iio_priv(indio_dev);
- s64 dat64[2];
- s32 *dat32 = (s32 *)dat64;
-
- if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength))
- __ad7192_read_reg(st, 1, 1, AD7192_REG_DATA,
- dat32,
- indio_dev->channels[0].scan_type.realbits/8);
-
- /* Guaranteed to be aligned with 8 byte boundary */
- if (indio_dev->scan_timestamp)
- dat64[1] = pf->timestamp;
-
- ring->access->store_to(ring, (u8 *)dat64, pf->timestamp);
-
- iio_trigger_notify_done(indio_dev->trig);
- st->irq_dis = false;
- enable_irq(st->spi->irq);
-
- return IRQ_HANDLED;
-}
-
-static const struct iio_buffer_setup_ops ad7192_ring_setup_ops = {
- .preenable = &ad7192_ring_preenable,
- .postenable = &iio_triggered_buffer_postenable,
- .predisable = &iio_triggered_buffer_predisable,
- .postdisable = &ad7192_ring_postdisable,
- .validate_scan_mask = &iio_validate_scan_mask_onehot,
-};
-
-static int ad7192_register_ring_funcs_and_init(struct iio_dev *indio_dev)
-{
- return iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,
- &ad7192_trigger_handler, &ad7192_ring_setup_ops);
-}
-
-static void ad7192_ring_cleanup(struct iio_dev *indio_dev)
-{
- iio_triggered_buffer_cleanup(indio_dev);
-}
-
-/**
- * ad7192_data_rdy_trig_poll() the event handler for the data rdy trig
- **/
-static irqreturn_t ad7192_data_rdy_trig_poll(int irq, void *private)
-{
- struct ad7192_state *st = iio_priv(private);
-
- st->done = true;
- wake_up_interruptible(&st->wq_data_avail);
- disable_irq_nosync(irq);
- st->irq_dis = true;
- iio_trigger_poll(st->trig, iio_get_time_ns());
-
- return IRQ_HANDLED;
-}
-
-static struct iio_trigger_ops ad7192_trigger_ops = {
- .owner = THIS_MODULE,
-};
-
-static int ad7192_probe_trigger(struct iio_dev *indio_dev)
-{
- struct ad7192_state *st = iio_priv(indio_dev);
- int ret;
-
- st->trig = iio_trigger_alloc("%s-dev%d",
- spi_get_device_id(st->spi)->name,
- indio_dev->id);
- if (st->trig == NULL) {
- ret = -ENOMEM;
- goto error_ret;
- }
- st->trig->ops = &ad7192_trigger_ops;
- ret = request_irq(st->spi->irq,
- ad7192_data_rdy_trig_poll,
- IRQF_TRIGGER_LOW,
- spi_get_device_id(st->spi)->name,
- indio_dev);
- if (ret)
- goto error_free_trig;
-
- disable_irq_nosync(st->spi->irq);
- st->irq_dis = true;
- st->trig->dev.parent = &st->spi->dev;
- st->trig->private_data = indio_dev;
-
- ret = iio_trigger_register(st->trig);
-
- /* select default trigger */
- indio_dev->trig = st->trig;
- if (ret)
- goto error_free_irq;
-
- return 0;
-
-error_free_irq:
- free_irq(st->spi->irq, indio_dev);
-error_free_trig:
- iio_trigger_free(st->trig);
-error_ret:
- return ret;
-}
-
-static void ad7192_remove_trigger(struct iio_dev *indio_dev)
-{
- struct ad7192_state *st = iio_priv(indio_dev);
-
- iio_trigger_unregister(st->trig);
- free_irq(st->spi->irq, indio_dev);
- iio_trigger_free(st->trig);
-}
-
static ssize_t ad7192_read_frequency(struct device *dev,
struct device_attribute *attr,
char *buf)
@@ -661,7 +343,7 @@ static ssize_t ad7192_write_frequency(struct device *dev,
st->mode &= ~AD7192_MODE_RATE(-1);
st->mode |= AD7192_MODE_RATE(div);
- ad7192_write_reg(st, AD7192_REG_MODE, 3, st->mode);
+ ad_sd_write_reg(&st->sd, AD7192_REG_MODE, 3, st->mode);
out:
mutex_unlock(&indio_dev->mlock);
@@ -673,7 +355,6 @@ static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
ad7192_read_frequency,
ad7192_write_frequency);
-
static ssize_t ad7192_show_scale_available(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -745,7 +426,7 @@ static ssize_t ad7192_set(struct device *dev,
else
st->gpocon &= ~AD7192_GPOCON_BPDSW;
- ad7192_write_reg(st, AD7192_REG_GPOCON, 1, st->gpocon);
+ ad_sd_write_reg(&st->sd, AD7192_REG_GPOCON, 1, st->gpocon);
break;
case AD7192_REG_MODE:
if (val)
@@ -753,7 +434,7 @@ static ssize_t ad7192_set(struct device *dev,
else
st->mode &= ~AD7192_MODE_ACX;
- ad7192_write_reg(st, AD7192_REG_MODE, 3, st->mode);
+ ad_sd_write_reg(&st->sd, AD7192_REG_MODE, 3, st->mode);
break;
default:
ret = -EINVAL;
@@ -809,27 +490,11 @@ static int ad7192_read_raw(struct iio_dev *indio_dev,
long m)
{
struct ad7192_state *st = iio_priv(indio_dev);
- int ret, smpl = 0;
bool unipolar = !!(st->conf & AD7192_CONF_UNIPOLAR);
switch (m) {
case IIO_CHAN_INFO_RAW:
- mutex_lock(&indio_dev->mlock);
- if (iio_buffer_enabled(indio_dev))
- ret = -EBUSY;
- else
- ret = ad7192_read(st, chan->address,
- chan->scan_type.realbits / 8, &smpl);
- mutex_unlock(&indio_dev->mlock);
-
- if (ret < 0)
- return ret;
-
- *val = (smpl >> chan->scan_type.shift) &
- ((1 << (chan->scan_type.realbits)) - 1);
-
- return IIO_VAL_INT;
-
+ return ad_sigma_delta_single_conversion(indio_dev, chan, val);
case IIO_CHAN_INFO_SCALE:
switch (chan->type) {
case IIO_VOLTAGE:
@@ -880,16 +545,16 @@ static int ad7192_write_raw(struct iio_dev *indio_dev,
ret = -EINVAL;
for (i = 0; i < ARRAY_SIZE(st->scale_avail); i++)
if (val2 == st->scale_avail[i][1]) {
+ ret = 0;
tmp = st->conf;
st->conf &= ~AD7192_CONF_GAIN(-1);
st->conf |= AD7192_CONF_GAIN(i);
-
- if (tmp != st->conf) {
- ad7192_write_reg(st, AD7192_REG_CONF,
- 3, st->conf);
- ad7192_calibrate_all(st);
- }
- ret = 0;
+ if (tmp == st->conf)
+ break;
+ ad_sd_write_reg(&st->sd, AD7192_REG_CONF,
+ 3, st->conf);
+ ad7192_calibrate_all(st);
+ break;
}
break;
default:
@@ -901,15 +566,6 @@ static int ad7192_write_raw(struct iio_dev *indio_dev,
return ret;
}
-static int ad7192_validate_trigger(struct iio_dev *indio_dev,
- struct iio_trigger *trig)
-{
- if (indio_dev->trig != trig)
- return -EINVAL;
-
- return 0;
-}
-
static int ad7192_write_raw_get_fmt(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
long mask)
@@ -922,7 +578,7 @@ static const struct iio_info ad7192_info = {
.write_raw = &ad7192_write_raw,
.write_raw_get_fmt = &ad7192_write_raw_get_fmt,
.attrs = &ad7192_attribute_group,
- .validate_trigger = ad7192_validate_trigger,
+ .validate_trigger = ad_sd_validate_trigger,
.driver_module = THIS_MODULE,
};
@@ -931,54 +587,19 @@ static const struct iio_info ad7195_info = {
.write_raw = &ad7192_write_raw,
.write_raw_get_fmt = &ad7192_write_raw_get_fmt,
.attrs = &ad7195_attribute_group,
- .validate_trigger = ad7192_validate_trigger,
+ .validate_trigger = ad_sd_validate_trigger,
.driver_module = THIS_MODULE,
};
-#define AD7192_CHAN_DIFF(_chan, _chan2, _name, _address, _si) \
- { .type = IIO_VOLTAGE, \
- .differential = 1, \
- .indexed = 1, \
- .extend_name = _name, \
- .channel = _chan, \
- .channel2 = _chan2, \
- .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
- IIO_CHAN_INFO_SCALE_SHARED_BIT | \
- IIO_CHAN_INFO_OFFSET_SHARED_BIT, \
- .address = _address, \
- .scan_index = _si, \
- .scan_type = IIO_ST('u', 24, 32, 0)}
-
-#define AD7192_CHAN(_chan, _address, _si) \
- { .type = IIO_VOLTAGE, \
- .indexed = 1, \
- .channel = _chan, \
- .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
- IIO_CHAN_INFO_SCALE_SHARED_BIT | \
- IIO_CHAN_INFO_OFFSET_SHARED_BIT, \
- .address = _address, \
- .scan_index = _si, \
- .scan_type = IIO_ST('u', 24, 32, 0)}
-
-#define AD7192_CHAN_TEMP(_chan, _address, _si) \
- { .type = IIO_TEMP, \
- .indexed = 1, \
- .channel = _chan, \
- .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
- IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \
- .address = _address, \
- .scan_index = _si, \
- .scan_type = IIO_ST('u', 24, 32, 0)}
-
static const struct iio_chan_spec ad7192_channels[] = {
- AD7192_CHAN_DIFF(1, 2, NULL, AD7192_CH_AIN1P_AIN2M, 0),
- AD7192_CHAN_DIFF(3, 4, NULL, AD7192_CH_AIN3P_AIN4M, 1),
- AD7192_CHAN_TEMP(0, AD7192_CH_TEMP, 2),
- AD7192_CHAN_DIFF(2, 2, "shorted", AD7192_CH_AIN2P_AIN2M, 3),
- AD7192_CHAN(1, AD7192_CH_AIN1, 4),
- AD7192_CHAN(2, AD7192_CH_AIN2, 5),
- AD7192_CHAN(3, AD7192_CH_AIN3, 6),
- AD7192_CHAN(4, AD7192_CH_AIN4, 7),
+ AD_SD_DIFF_CHANNEL(0, 1, 2, AD7192_CH_AIN1P_AIN2M, 24, 32, 0),
+ AD_SD_DIFF_CHANNEL(1, 3, 4, AD7192_CH_AIN3P_AIN4M, 24, 32, 0),
+ AD_SD_TEMP_CHANNEL(2, AD7192_CH_TEMP, 24, 32, 0),
+ AD_SD_SHORTED_CHANNEL(3, 2, AD7192_CH_AIN2P_AIN2M, 24, 32, 0),
+ AD_SD_CHANNEL(4, 1, AD7192_CH_AIN1, 24, 32, 0),
+ AD_SD_CHANNEL(5, 2, AD7192_CH_AIN2, 24, 32, 0),
+ AD_SD_CHANNEL(6, 3, AD7192_CH_AIN3, 24, 32, 0),
+ AD_SD_CHANNEL(7, 4, AD7192_CH_AIN4, 24, 32, 0),
IIO_CHAN_SOFT_TIMESTAMP(8),
};
@@ -1022,7 +643,6 @@ static int __devinit ad7192_probe(struct spi_device *spi)
dev_warn(&spi->dev, "reference voltage undefined\n");
spi_set_drvdata(spi, indio_dev);
- st->spi = spi;
st->devid = spi_get_device_id(spi)->driver_data;
indio_dev->dev.parent = &spi->dev;
indio_dev->name = spi_get_device_id(spi)->name;
@@ -1034,16 +654,12 @@ static int __devinit ad7192_probe(struct spi_device *spi)
else
indio_dev->info = &ad7192_info;
- init_waitqueue_head(&st->wq_data_avail);
+ ad_sd_init(&st->sd, indio_dev, spi, &ad7192_sigma_delta_info);
- ret = ad7192_register_ring_funcs_and_init(indio_dev);
+ ret = ad_sd_setup_buffer_and_trigger(indio_dev);
if (ret)
goto error_disable_reg;
- ret = ad7192_probe_trigger(indio_dev);
- if (ret)
- goto error_ring_cleanup;
-
ret = ad7192_setup(st, pdata);
if (ret)
goto error_remove_trigger;
@@ -1054,9 +670,7 @@ static int __devinit ad7192_probe(struct spi_device *spi)
return 0;
error_remove_trigger:
- ad7192_remove_trigger(indio_dev);
-error_ring_cleanup:
- ad7192_ring_cleanup(indio_dev);
+ ad_sd_cleanup_buffer_and_trigger(indio_dev);
error_disable_reg:
if (!IS_ERR(st->reg))
regulator_disable(st->reg);
@@ -1075,8 +689,7 @@ static int ad7192_remove(struct spi_device *spi)
struct ad7192_state *st = iio_priv(indio_dev);
iio_device_unregister(indio_dev);
- ad7192_remove_trigger(indio_dev);
- ad7192_ring_cleanup(indio_dev);
+ ad_sd_cleanup_buffer_and_trigger(indio_dev);
if (!IS_ERR(st->reg)) {
regulator_disable(st->reg);
--
1.7.10.4
^ permalink raw reply related [flat|nested] 37+ messages in thread
* [PATCH 20/22] staging:iio:ad7793: Add support for ad7794/ad7795
2012-08-10 16:36 [PATCH 01/22] staging:iio:ad7793: Add missing break in switch statement Lars-Peter Clausen
` (17 preceding siblings ...)
2012-08-10 16:36 ` [PATCH 19/22] staging:iio:ad7192: " Lars-Peter Clausen
@ 2012-08-10 16:36 ` Lars-Peter Clausen
2012-08-10 16:36 ` [PATCH 21/22] staging:iio:ad7793: Add ad7785 support Lars-Peter Clausen
2012-08-10 16:36 ` [PATCH 22/22] staging:iio:adc: Add AD7791 driver Lars-Peter Clausen
20 siblings, 0 replies; 37+ messages in thread
From: Lars-Peter Clausen @ 2012-08-10 16:36 UTC (permalink / raw)
To: Jonathan Cameron; +Cc: linux-iio, drivers, Lars-Peter Clausen
The ad7794/ad7795 are similar to the ad7792/ad7793, but have 6 channels instead
of 3.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
---
drivers/staging/iio/adc/Kconfig | 6 +--
drivers/staging/iio/adc/ad7793.c | 81 ++++++++++++++++++++++++++------------
drivers/staging/iio/adc/ad7793.h | 10 ++++-
3 files changed, 66 insertions(+), 31 deletions(-)
diff --git a/drivers/staging/iio/adc/Kconfig b/drivers/staging/iio/adc/Kconfig
index 9525308..3894281 100644
--- a/drivers/staging/iio/adc/Kconfig
+++ b/drivers/staging/iio/adc/Kconfig
@@ -109,12 +109,12 @@ config AD7780
module will be called ad7780.
config AD7793
- tristate "Analog Devices AD7792 AD7793 ADC driver"
+ tristate "Analog Devices AD7793 and similar ADCs driver"
depends on SPI
select AD_SIGMA_DELTA
help
- Say yes here to build support for Analog Devices
- AD7792 and AD7793 SPI analog to digital converters (ADC).
+ Say yes here to build support for Analog Devices AD7792, AD7793, AD7794
+ and AD7795 SPI analog to digital converters (ADC).
If unsure, say N (but it's safe to say "Y").
To compile this driver as a module, choose M here: the
diff --git a/drivers/staging/iio/adc/ad7793.c b/drivers/staging/iio/adc/ad7793.c
index ba199fa..1c0f6a1 100644
--- a/drivers/staging/iio/adc/ad7793.c
+++ b/drivers/staging/iio/adc/ad7793.c
@@ -1,5 +1,5 @@
/*
- * AD7792/AD7793 SPI ADC driver
+ * AD7792/AD7793/AD7794/AD7795 SPI ADC driver
*
* Copyright 2011-2012 Analog Devices Inc.
*
@@ -37,7 +37,8 @@
*/
struct ad7793_chip_info {
- struct iio_chan_spec channel[7];
+ const struct iio_chan_spec *channels;
+ unsigned int num_channels;
};
struct ad7793_state {
@@ -55,6 +56,8 @@ struct ad7793_state {
enum ad7793_supported_device_ids {
ID_AD7792,
ID_AD7793,
+ ID_AD7794,
+ ID_AD7795,
};
static struct ad7793_state *ad_sigma_delta_to_ad7793(struct ad_sigma_delta *sd)
@@ -126,7 +129,7 @@ static int ad7793_setup(struct iio_dev *indio_dev,
id &= AD7793_ID_MASK;
- if (!((id == AD7792_ID) || (id == AD7793_ID))) {
+ if (!((id == AD7792_ID) || (id == AD7793_ID) || (id == AD7795_ID))) {
dev_err(&st->sd.spi->dev, "device ID query failed\n");
goto out;
}
@@ -154,7 +157,7 @@ static int ad7793_setup(struct iio_dev *indio_dev,
/* Populate available ADC input ranges */
for (i = 0; i < ARRAY_SIZE(st->scale_avail); i++) {
scale_uv = ((u64)st->int_vref_mv * 100000000)
- >> (st->chip_info->channel[0].scan_type.realbits -
+ >> (st->chip_info->channels[0].scan_type.realbits -
(!!(st->conf & AD7793_CONF_UNIPOLAR) ? 0 : 1));
scale_uv >>= i;
@@ -382,28 +385,52 @@ static const struct iio_info ad7793_info = {
.driver_module = THIS_MODULE,
};
+#define DECLARE_AD7793_CHANNELS(_name, _b, _sb) \
+const struct iio_chan_spec _name##_channels[] = { \
+ AD_SD_DIFF_CHANNEL(0, 0, 0, AD7793_CH_AIN1P_AIN1M, (_b), (_sb), 0), \
+ AD_SD_DIFF_CHANNEL(1, 1, 1, AD7793_CH_AIN2P_AIN2M, (_b), (_sb), 0), \
+ AD_SD_DIFF_CHANNEL(2, 2, 2, AD7793_CH_AIN3P_AIN3M, (_b), (_sb), 0), \
+ AD_SD_SHORTED_CHANNEL(3, 0, AD7793_CH_AIN1M_AIN1M, (_b), (_sb), 0), \
+ AD_SD_TEMP_CHANNEL(4, AD7793_CH_TEMP, (_b), (_sb), 0), \
+ AD_SD_SUPPLY_CHANNEL(5, 3, AD7793_CH_AVDD_MONITOR, (_b), (_sb), 0), \
+ IIO_CHAN_SOFT_TIMESTAMP(6), \
+}
+
+#define DECLARE_AD7795_CHANNELS(_name, _b, _sb) \
+const struct iio_chan_spec _name##_channels[] = { \
+ AD_SD_DIFF_CHANNEL(0, 0, 0, AD7793_CH_AIN1P_AIN1M, (_b), (_sb), 0), \
+ AD_SD_DIFF_CHANNEL(1, 1, 1, AD7793_CH_AIN2P_AIN2M, (_b), (_sb), 0), \
+ AD_SD_DIFF_CHANNEL(2, 2, 2, AD7793_CH_AIN3P_AIN3M, (_b), (_sb), 0), \
+ AD_SD_DIFF_CHANNEL(3, 3, 3, AD7795_CH_AIN4P_AIN4M, (_b), (_sb), 0), \
+ AD_SD_DIFF_CHANNEL(4, 4, 4, AD7795_CH_AIN5P_AIN5M, (_b), (_sb), 0), \
+ AD_SD_DIFF_CHANNEL(5, 5, 5, AD7795_CH_AIN6P_AIN6M, (_b), (_sb), 0), \
+ AD_SD_SHORTED_CHANNEL(6, 0, AD7795_CH_AIN1M_AIN1M, (_b), (_sb), 0), \
+ AD_SD_TEMP_CHANNEL(7, AD7793_CH_TEMP, (_b), (_sb), 0), \
+ AD_SD_SUPPLY_CHANNEL(8, 3, AD7793_CH_AVDD_MONITOR, (_b), (_sb), 0), \
+ IIO_CHAN_SOFT_TIMESTAMP(9), \
+}
+
+static DECLARE_AD7793_CHANNELS(ad7792, 16, 32);
+static DECLARE_AD7793_CHANNELS(ad7793, 24, 32);
+static DECLARE_AD7795_CHANNELS(ad7794, 16, 32);
+static DECLARE_AD7795_CHANNELS(ad7795, 24, 32);
+
static const struct ad7793_chip_info ad7793_chip_info_tbl[] = {
+ [ID_AD7792] = {
+ .channels = ad7792_channels,
+ .num_channels = ARRAY_SIZE(ad7792_channels),
+ },
[ID_AD7793] = {
- .channel = {
- AD_SD_DIFF_CHANNEL(0, 0, 0, AD7793_CH_AIN1P_AIN1M, 24, 32, 0),
- AD_SD_DIFF_CHANNEL(1, 1, 1, AD7793_CH_AIN2P_AIN2M, 24, 32, 0),
- AD_SD_DIFF_CHANNEL(2, 2, 2, AD7793_CH_AIN3P_AIN3M, 24, 32, 0),
- AD_SD_SHORTED_CHANNEL(3, 0, AD7793_CH_AIN1M_AIN1M, 24, 32, 0),
- AD_SD_TEMP_CHANNEL(4, AD7793_CH_TEMP, 24, 32, 0),
- AD_SD_SUPPLY_CHANNEL(5, 3, AD7793_CH_AVDD_MONITOR, 24, 32, 0),
- IIO_CHAN_SOFT_TIMESTAMP(6),
- },
+ .channels = ad7793_channels,
+ .num_channels = ARRAY_SIZE(ad7793_channels),
},
- [ID_AD7792] = {
- .channel = {
- AD_SD_DIFF_CHANNEL(0, 0, 0, AD7793_CH_AIN1P_AIN1M, 16, 32, 0),
- AD_SD_DIFF_CHANNEL(1, 1, 1, AD7793_CH_AIN2P_AIN2M, 16, 32, 0),
- AD_SD_DIFF_CHANNEL(2, 2, 2, AD7793_CH_AIN3P_AIN3M, 16, 32, 0),
- AD_SD_SHORTED_CHANNEL(3, 0, AD7793_CH_AIN1M_AIN1M, 16, 32, 0),
- AD_SD_TEMP_CHANNEL(4, AD7793_CH_TEMP, 16, 32, 0),
- AD_SD_SUPPLY_CHANNEL(5, 3, AD7793_CH_AVDD_MONITOR, 16, 32, 0),
- IIO_CHAN_SOFT_TIMESTAMP(6),
- },
+ [ID_AD7794] = {
+ .channels = ad7794_channels,
+ .num_channels = ARRAY_SIZE(ad7794_channels),
+ },
+ [ID_AD7795] = {
+ .channels = ad7795_channels,
+ .num_channels = ARRAY_SIZE(ad7795_channels),
},
};
@@ -456,8 +483,8 @@ static int __devinit ad7793_probe(struct spi_device *spi)
indio_dev->dev.parent = &spi->dev;
indio_dev->name = spi_get_device_id(spi)->name;
indio_dev->modes = INDIO_DIRECT_MODE;
- indio_dev->channels = st->chip_info->channel;
- indio_dev->num_channels = 7;
+ indio_dev->channels = st->chip_info->channels;
+ indio_dev->num_channels = st->chip_info->num_channels;
indio_dev->info = &ad7793_info;
ret = ad_sd_setup_buffer_and_trigger(indio_dev);
@@ -509,6 +536,8 @@ static int ad7793_remove(struct spi_device *spi)
static const struct spi_device_id ad7793_id[] = {
{"ad7792", ID_AD7792},
{"ad7793", ID_AD7793},
+ {"ad7794", ID_AD7794},
+ {"ad7795", ID_AD7795},
{}
};
MODULE_DEVICE_TABLE(spi, ad7793_id);
@@ -525,5 +554,5 @@ static struct spi_driver ad7793_driver = {
module_spi_driver(ad7793_driver);
MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
-MODULE_DESCRIPTION("Analog Devices AD7792/3 ADC");
+MODULE_DESCRIPTION("Analog Devices AD7793 and simialr ADCs");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/iio/adc/ad7793.h b/drivers/staging/iio/adc/ad7793.h
index 0e296d8..8fdd450 100644
--- a/drivers/staging/iio/adc/ad7793.h
+++ b/drivers/staging/iio/adc/ad7793.h
@@ -70,8 +70,8 @@
#define AD7793_CONF_GAIN(x) (((x) & 0x7) << 8) /* Gain Select */
#define AD7793_CONF_REFSEL (1 << 7) /* INT/EXT Reference Select */
#define AD7793_CONF_BUF (1 << 4) /* Buffered Mode Enable */
-#define AD7793_CONF_CHAN(x) ((x) & 0x7) /* Channel select */
-#define AD7793_CONF_CHAN_MASK 0x7 /* Channel select mask */
+#define AD7793_CONF_CHAN(x) ((x) & 0xf) /* Channel select */
+#define AD7793_CONF_CHAN_MASK 0xf /* Channel select mask */
#define AD7793_CH_AIN1P_AIN1M 0 /* AIN1(+) - AIN1(-) */
#define AD7793_CH_AIN2P_AIN2M 1 /* AIN2(+) - AIN2(-) */
@@ -80,9 +80,15 @@
#define AD7793_CH_TEMP 6 /* Temp Sensor */
#define AD7793_CH_AVDD_MONITOR 7 /* AVDD Monitor */
+#define AD7795_CH_AIN4P_AIN4M 4 /* AIN4(+) - AIN4(-) */
+#define AD7795_CH_AIN5P_AIN5M 5 /* AIN5(+) - AIN5(-) */
+#define AD7795_CH_AIN6P_AIN6M 6 /* AIN6(+) - AIN6(-) */
+#define AD7795_CH_AIN1M_AIN1M 8 /* AIN1(-) - AIN1(-) */
+
/* ID Register Bit Designations (AD7793_REG_ID) */
#define AD7792_ID 0xA
#define AD7793_ID 0xB
+#define AD7795_ID 0xF
#define AD7793_ID_MASK 0xF
/* IO (Excitation Current Sources) Register Bit Designations (AD7793_REG_IO) */
--
1.7.10.4
^ permalink raw reply related [flat|nested] 37+ messages in thread
* [PATCH 21/22] staging:iio:ad7793: Add ad7785 support
2012-08-10 16:36 [PATCH 01/22] staging:iio:ad7793: Add missing break in switch statement Lars-Peter Clausen
` (18 preceding siblings ...)
2012-08-10 16:36 ` [PATCH 20/22] staging:iio:ad7793: Add support for ad7794/ad7795 Lars-Peter Clausen
@ 2012-08-10 16:36 ` Lars-Peter Clausen
2012-08-10 16:36 ` [PATCH 22/22] staging:iio:adc: Add AD7791 driver Lars-Peter Clausen
20 siblings, 0 replies; 37+ messages in thread
From: Lars-Peter Clausen @ 2012-08-10 16:36 UTC (permalink / raw)
To: Jonathan Cameron; +Cc: linux-iio, drivers, Lars-Peter Clausen
The ad7785 is similar to the ad7792/ad7793, but has 20 bit wide data samples.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
---
drivers/staging/iio/adc/Kconfig | 4 ++--
drivers/staging/iio/adc/ad7793.c | 27 +++++++++++++++++----------
2 files changed, 19 insertions(+), 12 deletions(-)
diff --git a/drivers/staging/iio/adc/Kconfig b/drivers/staging/iio/adc/Kconfig
index 3894281..57dbf6e 100644
--- a/drivers/staging/iio/adc/Kconfig
+++ b/drivers/staging/iio/adc/Kconfig
@@ -113,8 +113,8 @@ config AD7793
depends on SPI
select AD_SIGMA_DELTA
help
- Say yes here to build support for Analog Devices AD7792, AD7793, AD7794
- and AD7795 SPI analog to digital converters (ADC).
+ Say yes here to build support for Analog Devices AD7785, AD7792, AD7793,
+ AD7794 and AD7795 SPI analog to digital converters (ADC).
If unsure, say N (but it's safe to say "Y").
To compile this driver as a module, choose M here: the
diff --git a/drivers/staging/iio/adc/ad7793.c b/drivers/staging/iio/adc/ad7793.c
index 1c0f6a1..da57130 100644
--- a/drivers/staging/iio/adc/ad7793.c
+++ b/drivers/staging/iio/adc/ad7793.c
@@ -1,5 +1,5 @@
/*
- * AD7792/AD7793/AD7794/AD7795 SPI ADC driver
+ * AD7785/AD7792/AD7793/AD7794/AD7795 SPI ADC driver
*
* Copyright 2011-2012 Analog Devices Inc.
*
@@ -54,6 +54,7 @@ struct ad7793_state {
};
enum ad7793_supported_device_ids {
+ ID_AD7785,
ID_AD7792,
ID_AD7793,
ID_AD7794,
@@ -385,14 +386,14 @@ static const struct iio_info ad7793_info = {
.driver_module = THIS_MODULE,
};
-#define DECLARE_AD7793_CHANNELS(_name, _b, _sb) \
+#define DECLARE_AD7793_CHANNELS(_name, _b, _sb, _s) \
const struct iio_chan_spec _name##_channels[] = { \
- AD_SD_DIFF_CHANNEL(0, 0, 0, AD7793_CH_AIN1P_AIN1M, (_b), (_sb), 0), \
- AD_SD_DIFF_CHANNEL(1, 1, 1, AD7793_CH_AIN2P_AIN2M, (_b), (_sb), 0), \
- AD_SD_DIFF_CHANNEL(2, 2, 2, AD7793_CH_AIN3P_AIN3M, (_b), (_sb), 0), \
- AD_SD_SHORTED_CHANNEL(3, 0, AD7793_CH_AIN1M_AIN1M, (_b), (_sb), 0), \
- AD_SD_TEMP_CHANNEL(4, AD7793_CH_TEMP, (_b), (_sb), 0), \
- AD_SD_SUPPLY_CHANNEL(5, 3, AD7793_CH_AVDD_MONITOR, (_b), (_sb), 0), \
+ AD_SD_DIFF_CHANNEL(0, 0, 0, AD7793_CH_AIN1P_AIN1M, (_b), (_sb), (_s)), \
+ AD_SD_DIFF_CHANNEL(1, 1, 1, AD7793_CH_AIN2P_AIN2M, (_b), (_sb), (_s)), \
+ AD_SD_DIFF_CHANNEL(2, 2, 2, AD7793_CH_AIN3P_AIN3M, (_b), (_sb), (_s)), \
+ AD_SD_SHORTED_CHANNEL(3, 0, AD7793_CH_AIN1M_AIN1M, (_b), (_sb), (_s)), \
+ AD_SD_TEMP_CHANNEL(4, AD7793_CH_TEMP, (_b), (_sb), (_s)), \
+ AD_SD_SUPPLY_CHANNEL(5, 3, AD7793_CH_AVDD_MONITOR, (_b), (_sb), (_s)), \
IIO_CHAN_SOFT_TIMESTAMP(6), \
}
@@ -410,12 +411,17 @@ const struct iio_chan_spec _name##_channels[] = { \
IIO_CHAN_SOFT_TIMESTAMP(9), \
}
-static DECLARE_AD7793_CHANNELS(ad7792, 16, 32);
-static DECLARE_AD7793_CHANNELS(ad7793, 24, 32);
+static DECLARE_AD7793_CHANNELS(ad7785, 20, 32, 4);
+static DECLARE_AD7793_CHANNELS(ad7792, 16, 32, 0);
+static DECLARE_AD7793_CHANNELS(ad7793, 24, 32, 0);
static DECLARE_AD7795_CHANNELS(ad7794, 16, 32);
static DECLARE_AD7795_CHANNELS(ad7795, 24, 32);
static const struct ad7793_chip_info ad7793_chip_info_tbl[] = {
+ [ID_AD7785] = {
+ .channels = ad7785_channels,
+ .num_channels = ARRAY_SIZE(ad7785_channels),
+ },
[ID_AD7792] = {
.channels = ad7792_channels,
.num_channels = ARRAY_SIZE(ad7792_channels),
@@ -534,6 +540,7 @@ static int ad7793_remove(struct spi_device *spi)
}
static const struct spi_device_id ad7793_id[] = {
+ {"ad7785", ID_AD7785},
{"ad7792", ID_AD7792},
{"ad7793", ID_AD7793},
{"ad7794", ID_AD7794},
--
1.7.10.4
^ permalink raw reply related [flat|nested] 37+ messages in thread
* [PATCH 22/22] staging:iio:adc: Add AD7791 driver
2012-08-10 16:36 [PATCH 01/22] staging:iio:ad7793: Add missing break in switch statement Lars-Peter Clausen
` (19 preceding siblings ...)
2012-08-10 16:36 ` [PATCH 21/22] staging:iio:ad7793: Add ad7785 support Lars-Peter Clausen
@ 2012-08-10 16:36 ` Lars-Peter Clausen
2012-08-11 8:41 ` Peter Meerwald
2012-08-13 13:12 ` Lars-Peter Clausen
20 siblings, 2 replies; 37+ messages in thread
From: Lars-Peter Clausen @ 2012-08-10 16:36 UTC (permalink / raw)
To: Jonathan Cameron; +Cc: linux-iio, drivers, Lars-Peter Clausen
This patch adds support for the Analog Devices AD7787, AD7788, AD7789, AD7790
and AD7791 Sigma Delta Analog-to-Digital converters.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
---
drivers/iio/adc/Kconfig | 12 +
drivers/iio/adc/Makefile | 1 +
drivers/iio/adc/ad7791.c | 460 ++++++++++++++++++++++++++++++++++
include/linux/platform_data/ad7791.h | 17 ++
4 files changed, 490 insertions(+)
create mode 100644 drivers/iio/adc/ad7791.c
create mode 100644 include/linux/platform_data/ad7791.h
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index a2c5071..d0ae71e 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -18,6 +18,18 @@ config AD7266
Say yes here to build support for Analog Devices AD7265 and AD7266
ADCs.
+config AD7791
+ tristate "Analog Devices AD7791 ADC driver"
+ depends on SPI
+ select AD_SIGMA_DELTA
+ help
+ Say yes here to build support for Analog Devices AD7787, AD7788, AD7789,
+ AD7790 and AD7791 SPI analog to digital converters (ADC). If unsure, say
+ N (but it is safe to say "Y").
+
+ To compile this driver as a module, choose M here: the module will be
+ called ad7791.
+
config AT91_ADC
tristate "Atmel AT91 ADC"
depends on ARCH_AT91
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
index 5989356..f187ff6 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -4,4 +4,5 @@
obj-$(CONFIG_AD_SIGMA_DELTA) += ad_sigma_delta.o
obj-$(CONFIG_AD7266) += ad7266.o
+obj-$(CONFIG_AD7791) += ad7791.o
obj-$(CONFIG_AT91_ADC) += at91_adc.o
diff --git a/drivers/iio/adc/ad7791.c b/drivers/iio/adc/ad7791.c
new file mode 100644
index 0000000..56b9ffc
--- /dev/null
+++ b/drivers/iio/adc/ad7791.c
@@ -0,0 +1,460 @@
+/*
+ * AD7787/AD7788/AD7789/AD7790/AD7791 SPI ADC driver
+ *
+ * Copyright 2012 Analog Devices Inc.
+ * Author: Lars-Peter Clausen <lars@metafoo.de>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/sysfs.h>
+#include <linux/spi/spi.h>
+#include <linux/regulator/consumer.h>
+#include <linux/err.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
+#include <linux/iio/adc/ad_sigma_delta.h>
+
+#include <linux/platform_data/ad7791.h>
+
+#define AD7791_REG_COMM 0x0 /* For writes */
+#define AD7791_REG_STATUS 0x0 /* For reads */
+#define AD7791_REG_MODE 0x1
+#define AD7791_REG_FILTER 0x2
+#define AD7791_REG_DATA 0x3
+
+#define AD7791_MODE_CONTINUOUS 0x00
+#define AD7791_MODE_SINGLE 0x02
+#define AD7791_MODE_POWERDOWN 0x03
+
+#define AD7791_CH_AIN1P_AIN1N 0x00
+#define AD7791_CH_AIN2 0x01
+#define AD7791_CH_AIN1N_AIN1N 0x02
+#define AD7791_CH_AVDD_MONITOR 0x03
+
+#define AD7791_FILTER_CLK_DIV_1 (0x0 << 4)
+#define AD7791_FILTER_CLK_DIV_2 (0x1 << 4)
+#define AD7791_FILTER_CLK_DIV_4 (0x2 << 4)
+#define AD7791_FILTER_CLK_DIV_8 (0x3 << 4)
+#define AD7791_FILTER_CLK_MASK (0x3 << 4)
+#define AD7791_FILTER_RATE_120 0x0
+#define AD7791_FILTER_RATE_100 0x1
+#define AD7791_FILTER_RATE_33_3 0x2
+#define AD7791_FILTER_RATE_20 0x3
+#define AD7791_FILTER_RATE_16_6 0x4
+#define AD7791_FILTER_RATE_16_7 0x5
+#define AD7791_FILTER_RATE_13_3 0x6
+#define AD7791_FILTER_RATE_9_5 0x7
+#define AD7791_FILTER_RATE_MASK 0x7
+
+#define AD7791_MODE_BUFFER BIT(1)
+#define AD7791_MODE_UNIPOLAR BIT(2)
+#define AD7791_MODE_BURNOUT BIT(3)
+#define AD7791_MODE_SEL_MASK (0x3 << 6)
+#define AD7791_MODE_SEL(x) ((x) << 6)
+
+#define DECLARE_AD7787_CHANNELS(name, bits, storagebits) \
+const struct iio_chan_spec name[] = { \
+ AD_SD_DIFF_CHANNEL(0, 0, 0, AD7791_CH_AIN1P_AIN1N, \
+ (bits), (storagebits), 0), \
+ AD_SD_CHANNEL(1, 1, AD7791_CH_AIN2, (bits), (storagebits), 0), \
+ AD_SD_SHORTED_CHANNEL(2, 0, AD7791_CH_AIN1N_AIN1N, \
+ (bits), (storagebits), 0), \
+ AD_SD_SUPPLY_CHANNEL(3, 2, AD7791_CH_AVDD_MONITOR, \
+ (bits), (storagebits), 0), \
+ IIO_CHAN_SOFT_TIMESTAMP(4), \
+}
+
+#define DECLARE_AD7791_CHANNELS(name, bits, storagebits) \
+const struct iio_chan_spec name[] = { \
+ AD_SD_DIFF_CHANNEL(0, 0, 0, AD7791_CH_AIN1P_AIN1N, \
+ (bits), (storagebits), 0), \
+ AD_SD_SHORTED_CHANNEL(1, 0, AD7791_CH_AIN1N_AIN1N, \
+ (bits), (storagebits), 0), \
+ AD_SD_SUPPLY_CHANNEL(2, 1, AD7791_CH_AVDD_MONITOR, \
+ (bits), (storagebits), 0), \
+ IIO_CHAN_SOFT_TIMESTAMP(3), \
+}
+
+static DECLARE_AD7787_CHANNELS(ad7787_channels, 24, 32);
+static DECLARE_AD7791_CHANNELS(ad7790_channels, 16, 16);
+static DECLARE_AD7791_CHANNELS(ad7791_channels, 24, 32);
+
+enum {
+ AD7787,
+ AD7788,
+ AD7789,
+ AD7790,
+ AD7791,
+};
+
+enum ad7791_chip_info_flags {
+ AD7791_FLAG_HAS_FILTER = (1 << 0),
+ AD7791_FLAG_HAS_BUFFER = (1 << 1),
+ AD7791_FLAG_HAS_UNIPOLAR = (1 << 2),
+ AD7791_FLAG_HAS_BURNOUT = (1 << 3),
+};
+
+struct ad7791_chip_info {
+ const struct iio_chan_spec *channels;
+ unsigned int num_channels;
+ enum ad7791_chip_info_flags flags;
+};
+
+static const struct ad7791_chip_info ad7791_chip_infos[] = {
+ [AD7787] = {
+ .channels = ad7787_channels,
+ .num_channels = ARRAY_SIZE(ad7787_channels),
+ .flags = AD7791_FLAG_HAS_FILTER | AD7791_FLAG_HAS_BUFFER |
+ AD7791_FLAG_HAS_UNIPOLAR | AD7791_FLAG_HAS_BURNOUT,
+ },
+ [AD7788] = {
+ .channels = ad7790_channels,
+ .num_channels = ARRAY_SIZE(ad7790_channels),
+ .flags = AD7791_FLAG_HAS_UNIPOLAR,
+ },
+ [AD7789] = {
+ .channels = ad7791_channels,
+ .num_channels = ARRAY_SIZE(ad7791_channels),
+ .flags = AD7791_FLAG_HAS_UNIPOLAR,
+ },
+ [AD7790] = {
+ .channels = ad7790_channels,
+ .num_channels = ARRAY_SIZE(ad7790_channels),
+ .flags = AD7791_FLAG_HAS_FILTER | AD7791_FLAG_HAS_BUFFER |
+ AD7791_FLAG_HAS_BURNOUT,
+ },
+ [AD7791] = {
+ .channels = ad7791_channels,
+ .num_channels = ARRAY_SIZE(ad7791_channels),
+ .flags = AD7791_FLAG_HAS_FILTER | AD7791_FLAG_HAS_BUFFER |
+ AD7791_FLAG_HAS_UNIPOLAR | AD7791_FLAG_HAS_BURNOUT,
+ },
+};
+
+struct ad7791_state {
+ struct ad_sigma_delta sd;
+ uint8_t mode;
+ uint8_t filter;
+
+ struct regulator *reg;
+ const struct ad7791_chip_info *info;
+};
+
+static struct ad7791_state *ad_sigma_delta_to_ad7791(struct ad_sigma_delta *sd)
+{
+ return container_of(sd, struct ad7791_state, sd);
+}
+
+static int ad7791_set_channel(struct ad_sigma_delta *sd, unsigned int channel)
+{
+ ad_sd_set_comm(sd, channel);
+
+ return 0;
+}
+
+static int ad7791_set_mode(struct ad_sigma_delta *sd, unsigned int mode)
+{
+ struct ad7791_state *st = ad_sigma_delta_to_ad7791(sd);
+
+ switch (mode) {
+ case AD_SD_MODE_CONTINUOUS:
+ mode = AD7791_MODE_CONTINUOUS;
+ break;
+ case AD_SD_MODE_SINGLE:
+ mode = AD7791_MODE_SINGLE;
+ break;
+ case AD_SD_MODE_IDLE:
+ case AD_SD_MODE_POWERDOWN:
+ mode = AD7791_MODE_POWERDOWN;
+ break;
+ }
+
+ st->mode &= ~AD7791_MODE_SEL_MASK;
+ st->mode |= AD7791_MODE_SEL(mode);
+
+ return ad_sd_write_reg(sd, AD7791_REG_MODE, sizeof(st->mode), st->mode);
+}
+
+static const struct ad_sigma_delta_info ad7791_sigma_delta_info = {
+ .set_channel = ad7791_set_channel,
+ .set_mode = ad7791_set_mode,
+ .has_registers = true,
+ .addr_shift = 4,
+ .read_mask = BIT(3),
+};
+
+static int ad7791_read_raw(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan, int *val, int *val2, long info)
+{
+ struct ad7791_state *st = iio_priv(indio_dev);
+ unsigned long long scale_nv;
+ bool unipolar = !!(st->mode & AD7791_MODE_UNIPOLAR);
+
+ switch (info) {
+ case IIO_CHAN_INFO_RAW:
+ return ad_sigma_delta_single_conversion(indio_dev, chan, val);
+ case IIO_CHAN_INFO_OFFSET:
+ /**
+ * Unipolar: 0 to VREF
+ * Bipolar -VREF to VREF
+ **/
+ if (unipolar)
+ *val = 0;
+ else
+ *val = -(1 << (chan->scan_type.realbits - 1));
+ return IIO_VAL_INT;
+ case IIO_CHAN_INFO_SCALE:
+ /* The monitor channel uses an internal reference. */
+ if (chan->address == AD7791_CH_AVDD_MONITOR) {
+ scale_nv = 5850000000ULL;
+ } else {
+ int voltage_uv;
+
+ voltage_uv = regulator_get_voltage(st->reg);
+ if (voltage_uv < 0)
+ return voltage_uv;
+ scale_nv = voltage_uv * 1000;
+ }
+ if (unipolar)
+ scale_nv >>= chan->scan_type.realbits;
+ else
+ scale_nv >>= chan->scan_type.realbits - 1;
+ *val2 = do_div(scale_nv, 1000000);
+ *val = scale_nv;
+
+ return IIO_VAL_INT_PLUS_NANO;
+ }
+
+ return -EINVAL;
+}
+
+static const char * const ad7791_sample_freq_avail[] = {
+ [AD7791_FILTER_RATE_120] = "120",
+ [AD7791_FILTER_RATE_100] = "100",
+ [AD7791_FILTER_RATE_33_3] = "33.3",
+ [AD7791_FILTER_RATE_20] = "20",
+ [AD7791_FILTER_RATE_16_6] = "16.6",
+ [AD7791_FILTER_RATE_16_7] = "16.7",
+ [AD7791_FILTER_RATE_13_3] = "13.3",
+ [AD7791_FILTER_RATE_9_5] = "9.5",
+};
+
+static ssize_t ad7791_read_frequency(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ struct ad7791_state *st = iio_priv(indio_dev);
+ unsigned int rate = st->filter & AD7791_FILTER_RATE_MASK;
+
+ return sprintf(buf, "%s\n", ad7791_sample_freq_avail[rate]);
+}
+
+static ssize_t ad7791_write_frequency(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t len)
+{
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ struct ad7791_state *st = iio_priv(indio_dev);
+ int i, ret;
+
+ mutex_lock(&indio_dev->mlock);
+ if (iio_buffer_enabled(indio_dev)) {
+ mutex_unlock(&indio_dev->mlock);
+ return -EBUSY;
+ }
+ mutex_unlock(&indio_dev->mlock);
+
+ ret = -EINVAL;
+
+ for (i = 0; i < ARRAY_SIZE(ad7791_sample_freq_avail); i++) {
+ if (sysfs_streq(ad7791_sample_freq_avail[i], buf)) {
+
+ mutex_lock(&indio_dev->mlock);
+ st->filter &= ~AD7791_FILTER_RATE_MASK;
+ st->filter |= i;
+ ad_sd_write_reg(&st->sd, AD7791_REG_FILTER,
+ sizeof(st->filter), st->filter);
+ mutex_unlock(&indio_dev->mlock);
+ ret = 0;
+ break;
+ }
+ }
+
+ return ret ? ret : len;
+}
+
+static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
+ ad7791_read_frequency,
+ ad7791_write_frequency);
+
+static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("120 100 33.3 20 16.7 16.6 13.3 9.5");
+
+static struct attribute *ad7791_attributes[] = {
+ &iio_dev_attr_sampling_frequency.dev_attr.attr,
+ &iio_const_attr_sampling_frequency_available.dev_attr.attr,
+ NULL
+};
+
+static const struct attribute_group ad7791_attribute_group = {
+ .attrs = ad7791_attributes,
+};
+
+static const struct iio_info ad7791_info = {
+ .read_raw = &ad7791_read_raw,
+ .attrs = &ad7791_attribute_group,
+ .validate_trigger = ad_sd_validate_trigger,
+ .driver_module = THIS_MODULE,
+};
+
+static const struct iio_info ad7791_no_filter_info = {
+ .read_raw = &ad7791_read_raw,
+ .validate_trigger = ad_sd_validate_trigger,
+ .driver_module = THIS_MODULE,
+};
+
+static int __devinit ad7791_setup(struct ad7791_state *st,
+ struct ad7791_platform_data *pdata)
+{
+ /* Set to poweron-reset default values */
+ st->mode = AD7791_MODE_BUFFER;
+ st->filter = AD7791_FILTER_RATE_16_6;
+
+ if (!pdata)
+ return 0;
+
+ if ((st->info->flags & AD7791_FLAG_HAS_BUFFER) && !pdata->buffered)
+ st->mode &= ~AD7791_MODE_BUFFER;
+
+ if ((st->info->flags & AD7791_FLAG_HAS_BURNOUT) &&
+ pdata->burnout_current)
+ st->mode |= AD7791_MODE_BURNOUT;
+
+ if ((st->info->flags & AD7791_FLAG_HAS_UNIPOLAR) && pdata->unipolar)
+ st->mode |= AD7791_MODE_UNIPOLAR;
+
+ return ad_sd_write_reg(&st->sd, AD7791_REG_MODE, sizeof(st->mode),
+ st->mode);
+}
+
+static int __devinit ad7791_probe(struct spi_device *spi)
+{
+ struct ad7791_platform_data *pdata = spi->dev.platform_data;
+ struct iio_dev *indio_dev;
+ struct ad7791_state *st;
+ int ret;
+
+ if (!spi->irq) {
+ dev_err(&spi->dev, "Missing IRQ.\n");
+ return -ENXIO;
+ }
+
+ indio_dev = iio_device_alloc(sizeof(*st));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ st = iio_priv(indio_dev);
+
+ st->reg = regulator_get(&spi->dev, "refin");
+ if (IS_ERR(st->reg)) {
+ ret = PTR_ERR(st->reg);
+ goto err_iio_free;
+ }
+
+ ret = regulator_enable(st->reg);
+ if (ret)
+ goto error_put_reg;
+
+
+ st->info = &ad7791_chip_infos[spi_get_device_id(spi)->driver_data];
+ ad_sd_init(&st->sd, indio_dev, spi, &ad7791_sigma_delta_info);
+
+ spi_set_drvdata(spi, indio_dev);
+
+ indio_dev->dev.parent = &spi->dev;
+ indio_dev->name = spi_get_device_id(spi)->name;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->channels = st->info->channels;
+ indio_dev->num_channels = st->info->num_channels;
+ if (st->info->flags & AD7791_FLAG_HAS_FILTER)
+ indio_dev->info = &ad7791_info;
+ else
+ indio_dev->info = &ad7791_no_filter_info;
+
+ ret = ad_sd_setup_buffer_and_trigger(indio_dev);
+ if (ret)
+ goto error_disable_reg;
+
+ ret = ad7791_setup(st, pdata);
+ if (ret)
+ goto error_remove_trigger;
+
+ ret = iio_device_register(indio_dev);
+ if (ret)
+ goto error_remove_trigger;
+
+ return 0;
+
+error_remove_trigger:
+ ad_sd_cleanup_buffer_and_trigger(indio_dev);
+error_disable_reg:
+ regulator_disable(st->reg);
+error_put_reg:
+ regulator_put(st->reg);
+err_iio_free:
+ iio_device_free(indio_dev);
+
+ return ret;
+}
+
+static int __devexit ad7791_remove(struct spi_device *spi)
+{
+ struct iio_dev *indio_dev = spi_get_drvdata(spi);
+ struct ad7791_state *st = iio_priv(indio_dev);
+
+ iio_device_unregister(indio_dev);
+ ad_sd_cleanup_buffer_and_trigger(indio_dev);
+
+ regulator_disable(st->reg);
+ regulator_put(st->reg);
+
+ iio_device_free(indio_dev);
+
+ return 0;
+}
+
+static const struct spi_device_id ad7791_spi_ids[] = {
+ { "ad7787", AD7787 },
+ { "ad7788", AD7788 },
+ { "ad7789", AD7789 },
+ { "ad7790", AD7790 },
+ { "ad7791", AD7791 },
+ {}
+};
+MODULE_DEVICE_TABLE(spi, ad7791_spi_ids);
+
+static struct spi_driver ad7791_driver = {
+ .driver = {
+ .name = "ad7791",
+ .owner = THIS_MODULE,
+ },
+ .probe = ad7791_probe,
+ .remove = __devexit_p(ad7791_remove),
+ .id_table = ad7791_spi_ids,
+};
+module_spi_driver(ad7791_driver);
+
+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
+MODULE_DESCRIPTION("Analog Device AD7787/AD7788/AD7789/AD7790/AD7791 ADC driver");
+MODULE_LICENSE("GPL v2");
diff --git a/include/linux/platform_data/ad7791.h b/include/linux/platform_data/ad7791.h
new file mode 100644
index 0000000..317881f
--- /dev/null
+++ b/include/linux/platform_data/ad7791.h
@@ -0,0 +1,17 @@
+#ifndef __LINUX_PLATFORM_DATA_AD7791__
+#define __LINUX_PLATFORM_DATA_AD7791__
+
+/**
+ * struct ad7791_platform_data - AD7791 device platform data
+ * @buffered: If set to true configure the device for buffered input mode.
+ * @burnount_current: If set to true the 100mA burnout current is enabled.
+ * @unipolar: If set to true sample in unipolar mode, if set to false sample in
+ * bipolar mode.
+ */
+struct ad7791_platform_data {
+ bool buffered;
+ bool burnout_current;
+ bool unipolar;
+};
+
+#endif
--
1.7.10.4
^ permalink raw reply related [flat|nested] 37+ messages in thread
* Re: [PATCH 22/22] staging:iio:adc: Add AD7791 driver
2012-08-10 16:36 ` [PATCH 22/22] staging:iio:adc: Add AD7791 driver Lars-Peter Clausen
@ 2012-08-11 8:41 ` Peter Meerwald
2012-08-11 17:37 ` Lars-Peter Clausen
2012-08-13 13:12 ` Lars-Peter Clausen
1 sibling, 1 reply; 37+ messages in thread
From: Peter Meerwald @ 2012-08-11 8:41 UTC (permalink / raw)
To: Lars-Peter Clausen; +Cc: Jonathan Cameron, linux-iio, drivers
two minor comments below
> This patch adds support for the Analog Devices AD7787, AD7788, AD7789, AD7790
> and AD7791 Sigma Delta Analog-to-Digital converters.
>
> Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
> ---
> drivers/iio/adc/Kconfig | 12 +
> drivers/iio/adc/Makefile | 1 +
> drivers/iio/adc/ad7791.c | 460 ++++++++++++++++++++++++++++++++++
> include/linux/platform_data/ad7791.h | 17 ++
> 4 files changed, 490 insertions(+)
> create mode 100644 drivers/iio/adc/ad7791.c
> create mode 100644 include/linux/platform_data/ad7791.h
>
> diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
> index a2c5071..d0ae71e 100644
> --- a/drivers/iio/adc/Kconfig
> +++ b/drivers/iio/adc/Kconfig
> @@ -18,6 +18,18 @@ config AD7266
> Say yes here to build support for Analog Devices AD7265 and AD7266
> ADCs.
>
> +config AD7791
> + tristate "Analog Devices AD7791 ADC driver"
> + depends on SPI
> + select AD_SIGMA_DELTA
> + help
> + Say yes here to build support for Analog Devices AD7787, AD7788, AD7789,
> + AD7790 and AD7791 SPI analog to digital converters (ADC). If unsure, say
> + N (but it is safe to say "Y").
> +
> + To compile this driver as a module, choose M here: the module will be
> + called ad7791.
> +
> config AT91_ADC
> tristate "Atmel AT91 ADC"
> depends on ARCH_AT91
> diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
> index 5989356..f187ff6 100644
> --- a/drivers/iio/adc/Makefile
> +++ b/drivers/iio/adc/Makefile
> @@ -4,4 +4,5 @@
>
> obj-$(CONFIG_AD_SIGMA_DELTA) += ad_sigma_delta.o
> obj-$(CONFIG_AD7266) += ad7266.o
> +obj-$(CONFIG_AD7791) += ad7791.o
> obj-$(CONFIG_AT91_ADC) += at91_adc.o
> diff --git a/drivers/iio/adc/ad7791.c b/drivers/iio/adc/ad7791.c
> new file mode 100644
> index 0000000..56b9ffc
> --- /dev/null
> +++ b/drivers/iio/adc/ad7791.c
> @@ -0,0 +1,460 @@
> +/*
> + * AD7787/AD7788/AD7789/AD7790/AD7791 SPI ADC driver
> + *
> + * Copyright 2012 Analog Devices Inc.
> + * Author: Lars-Peter Clausen <lars@metafoo.de>
> + *
> + * Licensed under the GPL-2.
> + */
> +
> +#include <linux/interrupt.h>
> +#include <linux/device.h>
> +#include <linux/kernel.h>
> +#include <linux/slab.h>
> +#include <linux/sysfs.h>
> +#include <linux/spi/spi.h>
> +#include <linux/regulator/consumer.h>
> +#include <linux/err.h>
> +#include <linux/sched.h>
> +#include <linux/delay.h>
> +#include <linux/module.h>
> +
> +#include <linux/iio/iio.h>
> +#include <linux/iio/sysfs.h>
> +#include <linux/iio/buffer.h>
> +#include <linux/iio/trigger.h>
> +#include <linux/iio/trigger_consumer.h>
> +#include <linux/iio/triggered_buffer.h>
> +#include <linux/iio/adc/ad_sigma_delta.h>
> +
> +#include <linux/platform_data/ad7791.h>
> +
> +#define AD7791_REG_COMM 0x0 /* For writes */
> +#define AD7791_REG_STATUS 0x0 /* For reads */
> +#define AD7791_REG_MODE 0x1
> +#define AD7791_REG_FILTER 0x2
> +#define AD7791_REG_DATA 0x3
> +
> +#define AD7791_MODE_CONTINUOUS 0x00
> +#define AD7791_MODE_SINGLE 0x02
> +#define AD7791_MODE_POWERDOWN 0x03
> +
> +#define AD7791_CH_AIN1P_AIN1N 0x00
> +#define AD7791_CH_AIN2 0x01
> +#define AD7791_CH_AIN1N_AIN1N 0x02
> +#define AD7791_CH_AVDD_MONITOR 0x03
> +
> +#define AD7791_FILTER_CLK_DIV_1 (0x0 << 4)
> +#define AD7791_FILTER_CLK_DIV_2 (0x1 << 4)
> +#define AD7791_FILTER_CLK_DIV_4 (0x2 << 4)
> +#define AD7791_FILTER_CLK_DIV_8 (0x3 << 4)
> +#define AD7791_FILTER_CLK_MASK (0x3 << 4)
> +#define AD7791_FILTER_RATE_120 0x0
> +#define AD7791_FILTER_RATE_100 0x1
> +#define AD7791_FILTER_RATE_33_3 0x2
> +#define AD7791_FILTER_RATE_20 0x3
> +#define AD7791_FILTER_RATE_16_6 0x4
> +#define AD7791_FILTER_RATE_16_7 0x5
> +#define AD7791_FILTER_RATE_13_3 0x6
> +#define AD7791_FILTER_RATE_9_5 0x7
> +#define AD7791_FILTER_RATE_MASK 0x7
> +
> +#define AD7791_MODE_BUFFER BIT(1)
> +#define AD7791_MODE_UNIPOLAR BIT(2)
> +#define AD7791_MODE_BURNOUT BIT(3)
> +#define AD7791_MODE_SEL_MASK (0x3 << 6)
> +#define AD7791_MODE_SEL(x) ((x) << 6)
> +
> +#define DECLARE_AD7787_CHANNELS(name, bits, storagebits) \
> +const struct iio_chan_spec name[] = { \
> + AD_SD_DIFF_CHANNEL(0, 0, 0, AD7791_CH_AIN1P_AIN1N, \
> + (bits), (storagebits), 0), \
> + AD_SD_CHANNEL(1, 1, AD7791_CH_AIN2, (bits), (storagebits), 0), \
> + AD_SD_SHORTED_CHANNEL(2, 0, AD7791_CH_AIN1N_AIN1N, \
> + (bits), (storagebits), 0), \
> + AD_SD_SUPPLY_CHANNEL(3, 2, AD7791_CH_AVDD_MONITOR, \
> + (bits), (storagebits), 0), \
> + IIO_CHAN_SOFT_TIMESTAMP(4), \
> +}
> +
> +#define DECLARE_AD7791_CHANNELS(name, bits, storagebits) \
> +const struct iio_chan_spec name[] = { \
> + AD_SD_DIFF_CHANNEL(0, 0, 0, AD7791_CH_AIN1P_AIN1N, \
> + (bits), (storagebits), 0), \
> + AD_SD_SHORTED_CHANNEL(1, 0, AD7791_CH_AIN1N_AIN1N, \
> + (bits), (storagebits), 0), \
> + AD_SD_SUPPLY_CHANNEL(2, 1, AD7791_CH_AVDD_MONITOR, \
> + (bits), (storagebits), 0), \
> + IIO_CHAN_SOFT_TIMESTAMP(3), \
> +}
> +
> +static DECLARE_AD7787_CHANNELS(ad7787_channels, 24, 32);
> +static DECLARE_AD7791_CHANNELS(ad7790_channels, 16, 16);
> +static DECLARE_AD7791_CHANNELS(ad7791_channels, 24, 32);
> +
> +enum {
> + AD7787,
> + AD7788,
> + AD7789,
> + AD7790,
> + AD7791,
> +};
> +
> +enum ad7791_chip_info_flags {
> + AD7791_FLAG_HAS_FILTER = (1 << 0),
> + AD7791_FLAG_HAS_BUFFER = (1 << 1),
> + AD7791_FLAG_HAS_UNIPOLAR = (1 << 2),
> + AD7791_FLAG_HAS_BURNOUT = (1 << 3),
> +};
> +
> +struct ad7791_chip_info {
> + const struct iio_chan_spec *channels;
> + unsigned int num_channels;
> + enum ad7791_chip_info_flags flags;
> +};
> +
> +static const struct ad7791_chip_info ad7791_chip_infos[] = {
> + [AD7787] = {
> + .channels = ad7787_channels,
> + .num_channels = ARRAY_SIZE(ad7787_channels),
> + .flags = AD7791_FLAG_HAS_FILTER | AD7791_FLAG_HAS_BUFFER |
> + AD7791_FLAG_HAS_UNIPOLAR | AD7791_FLAG_HAS_BURNOUT,
> + },
> + [AD7788] = {
> + .channels = ad7790_channels,
> + .num_channels = ARRAY_SIZE(ad7790_channels),
> + .flags = AD7791_FLAG_HAS_UNIPOLAR,
> + },
> + [AD7789] = {
> + .channels = ad7791_channels,
> + .num_channels = ARRAY_SIZE(ad7791_channels),
> + .flags = AD7791_FLAG_HAS_UNIPOLAR,
> + },
> + [AD7790] = {
> + .channels = ad7790_channels,
> + .num_channels = ARRAY_SIZE(ad7790_channels),
> + .flags = AD7791_FLAG_HAS_FILTER | AD7791_FLAG_HAS_BUFFER |
> + AD7791_FLAG_HAS_BURNOUT,
> + },
> + [AD7791] = {
> + .channels = ad7791_channels,
> + .num_channels = ARRAY_SIZE(ad7791_channels),
> + .flags = AD7791_FLAG_HAS_FILTER | AD7791_FLAG_HAS_BUFFER |
> + AD7791_FLAG_HAS_UNIPOLAR | AD7791_FLAG_HAS_BURNOUT,
> + },
> +};
> +
> +struct ad7791_state {
> + struct ad_sigma_delta sd;
> + uint8_t mode;
> + uint8_t filter;
> +
> + struct regulator *reg;
> + const struct ad7791_chip_info *info;
> +};
> +
> +static struct ad7791_state *ad_sigma_delta_to_ad7791(struct ad_sigma_delta *sd)
> +{
> + return container_of(sd, struct ad7791_state, sd);
> +}
> +
> +static int ad7791_set_channel(struct ad_sigma_delta *sd, unsigned int channel)
> +{
> + ad_sd_set_comm(sd, channel);
> +
> + return 0;
> +}
> +
> +static int ad7791_set_mode(struct ad_sigma_delta *sd, unsigned int mode)
> +{
> + struct ad7791_state *st = ad_sigma_delta_to_ad7791(sd);
> +
> + switch (mode) {
> + case AD_SD_MODE_CONTINUOUS:
> + mode = AD7791_MODE_CONTINUOUS;
> + break;
> + case AD_SD_MODE_SINGLE:
> + mode = AD7791_MODE_SINGLE;
> + break;
> + case AD_SD_MODE_IDLE:
> + case AD_SD_MODE_POWERDOWN:
> + mode = AD7791_MODE_POWERDOWN;
> + break;
> + }
> +
> + st->mode &= ~AD7791_MODE_SEL_MASK;
> + st->mode |= AD7791_MODE_SEL(mode);
> +
> + return ad_sd_write_reg(sd, AD7791_REG_MODE, sizeof(st->mode), st->mode);
> +}
> +
> +static const struct ad_sigma_delta_info ad7791_sigma_delta_info = {
> + .set_channel = ad7791_set_channel,
> + .set_mode = ad7791_set_mode,
> + .has_registers = true,
> + .addr_shift = 4,
> + .read_mask = BIT(3),
> +};
> +
> +static int ad7791_read_raw(struct iio_dev *indio_dev,
> + const struct iio_chan_spec *chan, int *val, int *val2, long info)
> +{
> + struct ad7791_state *st = iio_priv(indio_dev);
> + unsigned long long scale_nv;
> + bool unipolar = !!(st->mode & AD7791_MODE_UNIPOLAR);
> +
> + switch (info) {
> + case IIO_CHAN_INFO_RAW:
> + return ad_sigma_delta_single_conversion(indio_dev, chan, val);
> + case IIO_CHAN_INFO_OFFSET:
> + /**
> + * Unipolar: 0 to VREF
> + * Bipolar -VREF to VREF
> + **/
> + if (unipolar)
> + *val = 0;
> + else
> + *val = -(1 << (chan->scan_type.realbits - 1));
> + return IIO_VAL_INT;
> + case IIO_CHAN_INFO_SCALE:
> + /* The monitor channel uses an internal reference. */
> + if (chan->address == AD7791_CH_AVDD_MONITOR) {
> + scale_nv = 5850000000ULL;
> + } else {
> + int voltage_uv;
> +
> + voltage_uv = regulator_get_voltage(st->reg);
> + if (voltage_uv < 0)
> + return voltage_uv;
> + scale_nv = voltage_uv * 1000;
> + }
> + if (unipolar)
> + scale_nv >>= chan->scan_type.realbits;
> + else
> + scale_nv >>= chan->scan_type.realbits - 1;
> + *val2 = do_div(scale_nv, 1000000);
> + *val = scale_nv;
> +
> + return IIO_VAL_INT_PLUS_NANO;
> + }
> +
> + return -EINVAL;
> +}
> +
> +static const char * const ad7791_sample_freq_avail[] = {
> + [AD7791_FILTER_RATE_120] = "120",
> + [AD7791_FILTER_RATE_100] = "100",
> + [AD7791_FILTER_RATE_33_3] = "33.3",
> + [AD7791_FILTER_RATE_20] = "20",
> + [AD7791_FILTER_RATE_16_6] = "16.6",
> + [AD7791_FILTER_RATE_16_7] = "16.7",
just curious; why is this not in strictly decreasing order?
IIO_CONST_ATTR_SAMP_FREQ_AVAIL is...
> + [AD7791_FILTER_RATE_13_3] = "13.3",
> + [AD7791_FILTER_RATE_9_5] = "9.5",
> +};
> +
> +static ssize_t ad7791_read_frequency(struct device *dev,
> + struct device_attribute *attr, char *buf)
> +{
> + struct iio_dev *indio_dev = dev_to_iio_dev(dev);
> + struct ad7791_state *st = iio_priv(indio_dev);
> + unsigned int rate = st->filter & AD7791_FILTER_RATE_MASK;
> +
> + return sprintf(buf, "%s\n", ad7791_sample_freq_avail[rate]);
> +}
> +
> +static ssize_t ad7791_write_frequency(struct device *dev,
> + struct device_attribute *attr, const char *buf, size_t len)
> +{
> + struct iio_dev *indio_dev = dev_to_iio_dev(dev);
> + struct ad7791_state *st = iio_priv(indio_dev);
> + int i, ret;
> +
> + mutex_lock(&indio_dev->mlock);
> + if (iio_buffer_enabled(indio_dev)) {
> + mutex_unlock(&indio_dev->mlock);
> + return -EBUSY;
> + }
> + mutex_unlock(&indio_dev->mlock);
> +
> + ret = -EINVAL;
> +
> + for (i = 0; i < ARRAY_SIZE(ad7791_sample_freq_avail); i++) {
> + if (sysfs_streq(ad7791_sample_freq_avail[i], buf)) {
> +
> + mutex_lock(&indio_dev->mlock);
> + st->filter &= ~AD7791_FILTER_RATE_MASK;
> + st->filter |= i;
> + ad_sd_write_reg(&st->sd, AD7791_REG_FILTER,
> + sizeof(st->filter), st->filter);
> + mutex_unlock(&indio_dev->mlock);
> + ret = 0;
> + break;
> + }
> + }
> +
> + return ret ? ret : len;
> +}
> +
> +static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
> + ad7791_read_frequency,
> + ad7791_write_frequency);
> +
> +static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("120 100 33.3 20 16.7 16.6 13.3 9.5");
> +
> +static struct attribute *ad7791_attributes[] = {
> + &iio_dev_attr_sampling_frequency.dev_attr.attr,
> + &iio_const_attr_sampling_frequency_available.dev_attr.attr,
> + NULL
> +};
> +
> +static const struct attribute_group ad7791_attribute_group = {
> + .attrs = ad7791_attributes,
> +};
> +
> +static const struct iio_info ad7791_info = {
> + .read_raw = &ad7791_read_raw,
> + .attrs = &ad7791_attribute_group,
> + .validate_trigger = ad_sd_validate_trigger,
> + .driver_module = THIS_MODULE,
> +};
> +
> +static const struct iio_info ad7791_no_filter_info = {
> + .read_raw = &ad7791_read_raw,
> + .validate_trigger = ad_sd_validate_trigger,
> + .driver_module = THIS_MODULE,
> +};
> +
> +static int __devinit ad7791_setup(struct ad7791_state *st,
> + struct ad7791_platform_data *pdata)
> +{
> + /* Set to poweron-reset default values */
> + st->mode = AD7791_MODE_BUFFER;
> + st->filter = AD7791_FILTER_RATE_16_6;
> +
> + if (!pdata)
> + return 0;
> +
> + if ((st->info->flags & AD7791_FLAG_HAS_BUFFER) && !pdata->buffered)
there's one extra space before !pdata->buffered
> + st->mode &= ~AD7791_MODE_BUFFER;
> +
> + if ((st->info->flags & AD7791_FLAG_HAS_BURNOUT) &&
> + pdata->burnout_current)
> + st->mode |= AD7791_MODE_BURNOUT;
> +
> + if ((st->info->flags & AD7791_FLAG_HAS_UNIPOLAR) && pdata->unipolar)
> + st->mode |= AD7791_MODE_UNIPOLAR;
> +
> + return ad_sd_write_reg(&st->sd, AD7791_REG_MODE, sizeof(st->mode),
> + st->mode);
> +}
> +
> +static int __devinit ad7791_probe(struct spi_device *spi)
> +{
> + struct ad7791_platform_data *pdata = spi->dev.platform_data;
> + struct iio_dev *indio_dev;
> + struct ad7791_state *st;
> + int ret;
> +
> + if (!spi->irq) {
> + dev_err(&spi->dev, "Missing IRQ.\n");
> + return -ENXIO;
> + }
> +
> + indio_dev = iio_device_alloc(sizeof(*st));
> + if (!indio_dev)
> + return -ENOMEM;
> +
> + st = iio_priv(indio_dev);
> +
> + st->reg = regulator_get(&spi->dev, "refin");
> + if (IS_ERR(st->reg)) {
> + ret = PTR_ERR(st->reg);
> + goto err_iio_free;
> + }
> +
> + ret = regulator_enable(st->reg);
> + if (ret)
> + goto error_put_reg;
> +
> +
> + st->info = &ad7791_chip_infos[spi_get_device_id(spi)->driver_data];
> + ad_sd_init(&st->sd, indio_dev, spi, &ad7791_sigma_delta_info);
> +
> + spi_set_drvdata(spi, indio_dev);
> +
> + indio_dev->dev.parent = &spi->dev;
> + indio_dev->name = spi_get_device_id(spi)->name;
> + indio_dev->modes = INDIO_DIRECT_MODE;
> + indio_dev->channels = st->info->channels;
> + indio_dev->num_channels = st->info->num_channels;
> + if (st->info->flags & AD7791_FLAG_HAS_FILTER)
> + indio_dev->info = &ad7791_info;
> + else
> + indio_dev->info = &ad7791_no_filter_info;
> +
> + ret = ad_sd_setup_buffer_and_trigger(indio_dev);
> + if (ret)
> + goto error_disable_reg;
> +
> + ret = ad7791_setup(st, pdata);
> + if (ret)
> + goto error_remove_trigger;
> +
> + ret = iio_device_register(indio_dev);
> + if (ret)
> + goto error_remove_trigger;
> +
> + return 0;
> +
> +error_remove_trigger:
> + ad_sd_cleanup_buffer_and_trigger(indio_dev);
> +error_disable_reg:
> + regulator_disable(st->reg);
> +error_put_reg:
> + regulator_put(st->reg);
> +err_iio_free:
> + iio_device_free(indio_dev);
> +
> + return ret;
> +}
> +
> +static int __devexit ad7791_remove(struct spi_device *spi)
> +{
> + struct iio_dev *indio_dev = spi_get_drvdata(spi);
> + struct ad7791_state *st = iio_priv(indio_dev);
> +
> + iio_device_unregister(indio_dev);
> + ad_sd_cleanup_buffer_and_trigger(indio_dev);
> +
> + regulator_disable(st->reg);
> + regulator_put(st->reg);
> +
> + iio_device_free(indio_dev);
> +
> + return 0;
> +}
> +
> +static const struct spi_device_id ad7791_spi_ids[] = {
> + { "ad7787", AD7787 },
> + { "ad7788", AD7788 },
> + { "ad7789", AD7789 },
> + { "ad7790", AD7790 },
> + { "ad7791", AD7791 },
> + {}
> +};
> +MODULE_DEVICE_TABLE(spi, ad7791_spi_ids);
> +
> +static struct spi_driver ad7791_driver = {
> + .driver = {
> + .name = "ad7791",
> + .owner = THIS_MODULE,
> + },
> + .probe = ad7791_probe,
> + .remove = __devexit_p(ad7791_remove),
> + .id_table = ad7791_spi_ids,
> +};
> +module_spi_driver(ad7791_driver);
> +
> +MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
> +MODULE_DESCRIPTION("Analog Device AD7787/AD7788/AD7789/AD7790/AD7791 ADC driver");
> +MODULE_LICENSE("GPL v2");
> diff --git a/include/linux/platform_data/ad7791.h b/include/linux/platform_data/ad7791.h
> new file mode 100644
> index 0000000..317881f
> --- /dev/null
> +++ b/include/linux/platform_data/ad7791.h
> @@ -0,0 +1,17 @@
> +#ifndef __LINUX_PLATFORM_DATA_AD7791__
> +#define __LINUX_PLATFORM_DATA_AD7791__
> +
> +/**
> + * struct ad7791_platform_data - AD7791 device platform data
> + * @buffered: If set to true configure the device for buffered input mode.
> + * @burnount_current: If set to true the 100mA burnout current is enabled.
burnout_current
> + * @unipolar: If set to true sample in unipolar mode, if set to false sample in
> + * bipolar mode.
> + */
> +struct ad7791_platform_data {
> + bool buffered;
> + bool burnout_current;
> + bool unipolar;
> +};
> +
> +#endif
>
--
Peter Meerwald
+43-664-2444418 (mobile)
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [PATCH 22/22] staging:iio:adc: Add AD7791 driver
2012-08-11 8:41 ` Peter Meerwald
@ 2012-08-11 17:37 ` Lars-Peter Clausen
0 siblings, 0 replies; 37+ messages in thread
From: Lars-Peter Clausen @ 2012-08-11 17:37 UTC (permalink / raw)
To: Peter Meerwald; +Cc: Jonathan Cameron, linux-iio, drivers
On 08/11/2012 10:41 AM, Peter Meerwald wrote:
>
> two minor comments below
>
Thanks.
>>[...]
>> +static const char * const ad7791_sample_freq_avail[] = {
>> + [AD7791_FILTER_RATE_120] = "120",
>> + [AD7791_FILTER_RATE_100] = "100",
>> + [AD7791_FILTER_RATE_33_3] = "33.3",
>> + [AD7791_FILTER_RATE_20] = "20",
>> + [AD7791_FILTER_RATE_16_6] = "16.6",
>> + [AD7791_FILTER_RATE_16_7] = "16.7",
>
> just curious; why is this not in strictly decreasing order?
> IIO_CONST_ATTR_SAMP_FREQ_AVAIL is...
It doesn't really matter, but to keep the indices in order.
AD7791_FILTER_RATE_16_6 is 0x4 and AD7791_FILTER_RATE_16_7 is 0x5.
>
>> + [AD7791_FILTER_RATE_13_3] = "13.3",
>> + [AD7791_FILTER_RATE_9_5] = "9.5",
>> +};
>> +
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [PATCH 22/22] staging:iio:adc: Add AD7791 driver
2012-08-10 16:36 ` [PATCH 22/22] staging:iio:adc: Add AD7791 driver Lars-Peter Clausen
2012-08-11 8:41 ` Peter Meerwald
@ 2012-08-13 13:12 ` Lars-Peter Clausen
2012-08-14 20:18 ` Jonathan Cameron
1 sibling, 1 reply; 37+ messages in thread
From: Lars-Peter Clausen @ 2012-08-13 13:12 UTC (permalink / raw)
To: Lars-Peter Clausen; +Cc: Jonathan Cameron, linux-iio, drivers
On 08/10/2012 06:36 PM, Lars-Peter Clausen wrote:
> This patch adds support for the Analog Devices AD7787, AD7788, AD7789, AD7790
> and AD7791 Sigma Delta Analog-to-Digital converters.
>
> Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
> ---
> [...]
> + case IIO_CHAN_INFO_SCALE:
> + /* The monitor channel uses an internal reference. */
> + if (chan->address == AD7791_CH_AVDD_MONITOR) {
> + scale_nv = 5850000000ULL;
> + } else {
> + int voltage_uv;
> +
> + voltage_uv = regulator_get_voltage(st->reg);
> + if (voltage_uv < 0)
> + return voltage_uv;
> + scale_nv = voltage_uv * 1000;
> + }
> + if (unipolar)
> + scale_nv >>= chan->scan_type.realbits;
> + else
> + scale_nv >>= chan->scan_type.realbits - 1;
> + *val2 = do_div(scale_nv, 1000000);
> + *val = scale_nv;
> +
Just noticed that the scale is off by a factor of 1000. It reports volts
while we want milli volts.
> + return IIO_VAL_INT_PLUS_NANO;
> + }
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [PATCH 16/22] iio:adc: Add common code for ADI Sigma Delta devices
2012-08-10 16:36 ` [PATCH 16/22] iio:adc: Add common code for ADI Sigma Delta devices Lars-Peter Clausen
@ 2012-08-14 12:03 ` Jonathan Cameron
2012-08-14 20:19 ` Jonathan Cameron
1 sibling, 0 replies; 37+ messages in thread
From: Jonathan Cameron @ 2012-08-14 12:03 UTC (permalink / raw)
To: Lars-Peter Clausen; +Cc: Jonathan Cameron, linux-iio, drivers
On 10/08/12 17:36, Lars-Peter Clausen wrote:
> Most devices from the Analog Devices Sigma Delta family use a similar scheme for
> communication with the device. This includes register access, as well as trigger
> handling. But each device sub-family has different features and different
> register layouts (some even have no registers at all) and thus it is impractical
> to try to support all of the devices by the same driver. This patch adds a
> common base library for Sigma Delta converter devices. It will be used by
> individual drivers.
>
> This code is mostly based on the three existing Sigma Delta drivers the AD7192,
> AD7780 and AD7793, but has been improved for more robustness and flexibility.
A minor point that you may want to fix is that some kerneldoc lines
don't have a short description of the function. If it is valid, it is
certainly ugly ;)
It's fine as it stands though so I'll merge this one as it stands.
>
> Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
> ---
> drivers/iio/adc/Kconfig | 5 +
> drivers/iio/adc/Makefile | 1 +
> drivers/iio/adc/ad_sigma_delta.c | 557 ++++++++++++++++++++++++++++++++
> include/linux/iio/adc/ad_sigma_delta.h | 173 ++++++++++
> 4 files changed, 736 insertions(+)
> create mode 100644 drivers/iio/adc/ad_sigma_delta.c
> create mode 100644 include/linux/iio/adc/ad_sigma_delta.h
>
> diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
> index 8a78b4f..a2c5071 100644
> --- a/drivers/iio/adc/Kconfig
> +++ b/drivers/iio/adc/Kconfig
> @@ -3,6 +3,11 @@
> #
> menu "Analog to digital converters"
>
> +config AD_SIGMA_DELTA
> + tristate
> + select IIO_BUFFER
> + select IIO_TRIGGERED_BUFFER
> +
> config AD7266
> tristate "Analog Devices AD7265/AD7266 ADC driver"
> depends on SPI_MASTER
> diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
> index 52eec25..5989356 100644
> --- a/drivers/iio/adc/Makefile
> +++ b/drivers/iio/adc/Makefile
> @@ -2,5 +2,6 @@
> # Makefile for IIO ADC drivers
> #
>
> +obj-$(CONFIG_AD_SIGMA_DELTA) += ad_sigma_delta.o
> obj-$(CONFIG_AD7266) += ad7266.o
> obj-$(CONFIG_AT91_ADC) += at91_adc.o
> diff --git a/drivers/iio/adc/ad_sigma_delta.c b/drivers/iio/adc/ad_sigma_delta.c
> new file mode 100644
> index 0000000..555feb7
> --- /dev/null
> +++ b/drivers/iio/adc/ad_sigma_delta.c
> @@ -0,0 +1,557 @@
> +/*
> + * Support code for Analog Devices Sigma-Delta ADCs
> + *
> + * Copyright 2012 Analog Devices Inc.
> + * Author: Lars-Peter Clausen <lars@metafoo.de>
> + *
> + * Licensed under the GPL-2.
> + */
> +
> +#include <linux/interrupt.h>
> +#include <linux/device.h>
> +#include <linux/kernel.h>
> +#include <linux/slab.h>
> +#include <linux/spi/spi.h>
> +#include <linux/err.h>
> +#include <linux/module.h>
> +
> +#include <linux/iio/iio.h>
> +#include <linux/iio/sysfs.h>
> +#include <linux/iio/buffer.h>
> +#include <linux/iio/trigger.h>
> +#include <linux/iio/trigger_consumer.h>
> +#include <linux/iio/triggered_buffer.h>
> +#include <linux/iio/adc/ad_sigma_delta.h>
> +
> +#include <asm/unaligned.h>
> +
> +
> +#define AD_SD_COMM_CHAN_MASK 0x3
> +
> +#define AD_SD_REG_COMM 0x00
> +#define AD_SD_REG_DATA 0x03
> +
> +/**
> + * ad_sd_set_comm() - Set communications register
> + *
> + * @sigma_delta: The sigma delta device
> + * @comm: New value for the communications register
> + */
> +void ad_sd_set_comm(struct ad_sigma_delta *sigma_delta, uint8_t comm)
> +{
> + /* Some variants use the lower two bits of the communications register
> + * to select the channel */
> + sigma_delta->comm = comm & AD_SD_COMM_CHAN_MASK;
> +}
> +EXPORT_SYMBOL_GPL(ad_sd_set_comm);
> +
> +/**
> + * ad_sd_write_reg() - Write a register
> + *
> + * @sigma_delta: The sigma delta device
> + * @reg: Address of the register
> + * @size: Size of the register (0-3)
> + * @val: Value to write to the register
> + *
> + * Returns 0 on success, an error code otherwise.
> + **/
> +int ad_sd_write_reg(struct ad_sigma_delta *sigma_delta, unsigned int reg,
> + unsigned int size, unsigned int val)
> +{
> + uint8_t *data = sigma_delta->data;
> + struct spi_transfer t = {
> + .tx_buf = data,
> + .len = size + 1,
> + .cs_change = sigma_delta->bus_locked,
> + };
> + struct spi_message m;
> + int ret;
> +
> + data[0] = (reg << sigma_delta->info->addr_shift) | sigma_delta->comm;
> +
> + switch (size) {
> + case 3:
> + data[1] = val >> 16;
> + data[2] = val >> 8;
> + data[3] = val;
> + break;
> + case 2:
> + put_unaligned_be16(val, &data[1]);
> + break;
> + case 1:
> + data[1] = val;
> + break;
> + case 0:
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + spi_message_init(&m);
> + spi_message_add_tail(&t, &m);
> +
> + if (sigma_delta->bus_locked)
> + ret = spi_sync_locked(sigma_delta->spi, &m);
> + else
> + ret = spi_sync(sigma_delta->spi, &m);
> +
> + return ret;
> +}
> +EXPORT_SYMBOL_GPL(ad_sd_write_reg);
> +
> +static int ad_sd_read_reg_raw(struct ad_sigma_delta *sigma_delta,
> + unsigned int reg, unsigned int size, uint8_t *val)
> +{
> + uint8_t *data = sigma_delta->data;
> + int ret;
> + struct spi_transfer t[] = {
> + {
> + .tx_buf = data,
> + .len = 1,
> + }, {
> + .rx_buf = val,
> + .len = size,
> + .cs_change = sigma_delta->bus_locked,
> + },
> + };
> + struct spi_message m;
> +
> + spi_message_init(&m);
> +
> + if (sigma_delta->info->has_registers) {
> + data[0] = reg << sigma_delta->info->addr_shift;
> + data[0] |= sigma_delta->info->read_mask;
> + spi_message_add_tail(&t[0], &m);
> + }
> + spi_message_add_tail(&t[1], &m);
> +
> + if (sigma_delta->bus_locked)
> + ret = spi_sync_locked(sigma_delta->spi, &m);
> + else
> + ret = spi_sync(sigma_delta->spi, &m);
> +
> + return ret;
> +}
> +
> +/**
> + * ad_sd_read_reg() - Read a register
> + *
> + * @sigma_delta: The sigma delta device
> + * @reg: Address of the register
> + * @size: Size of the register (1-4)
> + * @val: Read value
> + *
> + * Returns 0 on success, an error code otherwise.
> + **/
> +int ad_sd_read_reg(struct ad_sigma_delta *sigma_delta,
> + unsigned int reg, unsigned int size, unsigned int *val)
> +{
> + int ret;
> +
> + ret = ad_sd_read_reg_raw(sigma_delta, reg, size, sigma_delta->data);
> + if (ret < 0)
> + goto out;
> +
> + switch (size) {
> + case 4:
> + *val = get_unaligned_be32(sigma_delta->data);
> + break;
> + case 3:
> + *val = (sigma_delta->data[0] << 16) |
> + (sigma_delta->data[1] << 8) |
> + sigma_delta->data[2];
> + break;
> + case 2:
> + *val = get_unaligned_be16(sigma_delta->data);
> + break;
> + case 1:
> + *val = sigma_delta->data[0];
> + break;
> + default:
> + ret = -EINVAL;
> + break;
> + }
> +
> +out:
> + return ret;
> +}
> +EXPORT_SYMBOL_GPL(ad_sd_read_reg);
> +
> +static int ad_sd_calibrate(struct ad_sigma_delta *sigma_delta,
> + unsigned int mode, unsigned int channel)
> +{
> + int ret;
> +
> + ret = ad_sigma_delta_set_channel(sigma_delta, channel);
> + if (ret)
> + return ret;
> +
> + spi_bus_lock(sigma_delta->spi->master);
> + sigma_delta->bus_locked = true;
> + INIT_COMPLETION(sigma_delta->completion);
> +
> + ret = ad_sigma_delta_set_mode(sigma_delta, mode);
> + if (ret < 0)
> + goto out;
> +
> + sigma_delta->irq_dis = false;
> + enable_irq(sigma_delta->spi->irq);
> + ret = wait_for_completion_timeout(&sigma_delta->completion, 2*HZ);
> + if (ret == 0) {
> + sigma_delta->irq_dis = true;
> + disable_irq_nosync(sigma_delta->spi->irq);
> + ret = -EIO;
> + } else {
> + ret = 0;
> + }
> +out:
> + sigma_delta->bus_locked = false;
> + spi_bus_unlock(sigma_delta->spi->master);
> + ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_IDLE);
> +
> + return ret;
> +}
> +
> +/**
> + * ad_sd_calibrate_all() - Performs channel calibration
> + * @sigma_delta: The sigma delta device
> + * @cb: Array of channels and calibration type to perform
> + * @n: Number of items in cb
> + *
> + * Returns 0 on success, an error code otherwise.
> + **/
> +int ad_sd_calibrate_all(struct ad_sigma_delta *sigma_delta,
> + const struct ad_sd_calib_data *cb, unsigned int n)
> +{
> + unsigned int i;
> + int ret;
> +
> + for (i = 0; i < n; i++) {
> + ret = ad_sd_calibrate(sigma_delta, cb[i].mode, cb[i].channel);
> + if (ret)
> + return ret;
> + }
> +
> + return 0;
> +}
> +EXPORT_SYMBOL_GPL(ad_sd_calibrate_all);
> +
> +/**
> + * ad_sigma_delta_single_conversion() - Performs a single data conversion
> + * @indio_dev: The IIO device
> + * @chan: The conversion is done for this channel
> + * @val: Pointer to the location where to store the read value
> + *
> + * Returns: 0 on success, an error value otherwise.
> + */
> +int ad_sigma_delta_single_conversion(struct iio_dev *indio_dev,
> + const struct iio_chan_spec *chan, int *val)
> +{
> + struct ad_sigma_delta *sigma_delta = iio_device_get_drvdata(indio_dev);
> + unsigned int sample, raw_sample;
> + int ret = 0;
> +
> + if (iio_buffer_enabled(indio_dev))
> + return -EBUSY;
> +
> + mutex_lock(&indio_dev->mlock);
> + ad_sigma_delta_set_channel(sigma_delta, chan->address);
> +
> + spi_bus_lock(sigma_delta->spi->master);
> + sigma_delta->bus_locked = true;
> + INIT_COMPLETION(sigma_delta->completion);
> +
> + ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_SINGLE);
> +
> + sigma_delta->irq_dis = false;
> + enable_irq(sigma_delta->spi->irq);
> + ret = wait_for_completion_interruptible_timeout(
> + &sigma_delta->completion, HZ);
> +
> + sigma_delta->bus_locked = false;
> + spi_bus_unlock(sigma_delta->spi->master);
> +
> + if (ret == 0)
> + ret = -EIO;
> + if (ret < 0)
> + goto out;
> +
> + ret = ad_sd_read_reg(sigma_delta, AD_SD_REG_DATA,
> + DIV_ROUND_UP(chan->scan_type.realbits + chan->scan_type.shift, 8),
> + &raw_sample);
> +
> +out:
> + if (!sigma_delta->irq_dis) {
> + disable_irq_nosync(sigma_delta->spi->irq);
> + sigma_delta->irq_dis = true;
> + }
> +
> + ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_IDLE);
> + mutex_unlock(&indio_dev->mlock);
> +
> + if (ret)
> + return ret;
> +
> + sample = raw_sample >> chan->scan_type.shift;
> + sample &= (1 << chan->scan_type.realbits) - 1;
> + *val = sample;
> +
> + ret = ad_sigma_delta_postprocess_sample(sigma_delta, raw_sample);
> + if (ret)
> + return ret;
> +
> + return IIO_VAL_INT;
> +}
> +EXPORT_SYMBOL_GPL(ad_sigma_delta_single_conversion);
> +
> +static int ad_sd_buffer_postenable(struct iio_dev *indio_dev)
> +{
> + struct ad_sigma_delta *sigma_delta = iio_device_get_drvdata(indio_dev);
> + unsigned int channel;
> + int ret;
> +
> + ret = iio_triggered_buffer_postenable(indio_dev);
> + if (ret < 0)
> + return ret;
> +
> + channel = find_first_bit(indio_dev->active_scan_mask,
> + indio_dev->masklength);
> + ret = ad_sigma_delta_set_channel(sigma_delta,
> + indio_dev->channels[channel].address);
> + if (ret)
> + goto err_predisable;
> +
> + spi_bus_lock(sigma_delta->spi->master);
> + sigma_delta->bus_locked = true;
> + ret = ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_CONTINUOUS);
> + if (ret)
> + goto err_unlock;
> +
> + sigma_delta->irq_dis = false;
> + enable_irq(sigma_delta->spi->irq);
> +
> + return 0;
> +
> +err_unlock:
> + spi_bus_unlock(sigma_delta->spi->master);
> +err_predisable:
> +
> + return ret;
> +}
> +
> +static int ad_sd_buffer_postdisable(struct iio_dev *indio_dev)
> +{
> + struct ad_sigma_delta *sigma_delta = iio_device_get_drvdata(indio_dev);
> +
> + INIT_COMPLETION(sigma_delta->completion);
> + wait_for_completion_timeout(&sigma_delta->completion, HZ);
> +
> + if (!sigma_delta->irq_dis) {
> + disable_irq_nosync(sigma_delta->spi->irq);
> + sigma_delta->irq_dis = true;
> + }
> +
> + ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_IDLE);
> +
> + sigma_delta->bus_locked = false;
> + return spi_bus_unlock(sigma_delta->spi->master);
> +}
> +
> +static irqreturn_t ad_sd_trigger_handler(int irq, void *p)
> +{
> + struct iio_poll_func *pf = p;
> + struct iio_dev *indio_dev = pf->indio_dev;
> + struct ad_sigma_delta *sigma_delta = iio_device_get_drvdata(indio_dev);
> + unsigned int reg_size;
> + uint8_t data[16];
> + int ret;
> +
> + memset(data, 0x00, 16);
> +
> + /* Guaranteed to be aligned with 8 byte boundary */
> + if (indio_dev->scan_timestamp)
> + ((s64 *)data)[1] = pf->timestamp;
> +
> + reg_size = indio_dev->channels[0].scan_type.realbits +
> + indio_dev->channels[0].scan_type.shift;
> + reg_size = DIV_ROUND_UP(reg_size, 8);
> +
> + switch (reg_size) {
> + case 4:
> + case 2:
> + case 1:
> + ret = ad_sd_read_reg_raw(sigma_delta, AD_SD_REG_DATA,
> + reg_size, &data[0]);
> + break;
> + case 3:
> + /* We store 24 bit samples in a 32 bit word. Keep the upper
> + * byte set to zero. */
> + ret = ad_sd_read_reg_raw(sigma_delta, AD_SD_REG_DATA,
> + reg_size, &data[1]);
> + break;
> + }
> +
> + iio_push_to_buffer(indio_dev->buffer, (uint8_t *)data, pf->timestamp);
> +
> + iio_trigger_notify_done(indio_dev->trig);
> + sigma_delta->irq_dis = false;
> + enable_irq(sigma_delta->spi->irq);
> +
> + return IRQ_HANDLED;
> +}
> +
> +static const struct iio_buffer_setup_ops ad_sd_buffer_setup_ops = {
> + .preenable = &iio_sw_buffer_preenable,
> + .postenable = &ad_sd_buffer_postenable,
> + .predisable = &iio_triggered_buffer_predisable,
> + .postdisable = &ad_sd_buffer_postdisable,
> + .validate_scan_mask = &iio_validate_scan_mask_onehot,
> +};
> +
> +static irqreturn_t ad_sd_data_rdy_trig_poll(int irq, void *private)
> +{
> + struct ad_sigma_delta *sigma_delta = private;
> +
> + complete(&sigma_delta->completion);
> + disable_irq_nosync(irq);
> + sigma_delta->irq_dis = true;
> + iio_trigger_poll(sigma_delta->trig, iio_get_time_ns());
> +
> + return IRQ_HANDLED;
> +}
> +
> +/**
> + * ad_sd_validate_trigger() - validate_trigger callback for ad_sigma_delta devices
> + * @indio_dev: The IIO device
> + * @trig: The new trigger
> + *
> + * Returns: 0 if the 'trig' matches the trigger registered by the ad_sigma_delta
> + * device, -EINVAL otherwise.
> + */
> +int ad_sd_validate_trigger(struct iio_dev *indio_dev, struct iio_trigger *trig)
> +{
> + struct ad_sigma_delta *sigma_delta = iio_device_get_drvdata(indio_dev);
> +
> + if (sigma_delta->trig != trig)
> + return -EINVAL;
> +
> + return 0;
> +}
> +EXPORT_SYMBOL_GPL(ad_sd_validate_trigger);
> +
> +static const struct iio_trigger_ops ad_sd_trigger_ops = {
> + .owner = THIS_MODULE,
> +};
> +
> +static int ad_sd_probe_trigger(struct iio_dev *indio_dev)
> +{
> + struct ad_sigma_delta *sigma_delta = iio_device_get_drvdata(indio_dev);
> + int ret;
> +
> + sigma_delta->trig = iio_trigger_alloc("%s-dev%d", indio_dev->name,
> + indio_dev->id);
> + if (sigma_delta->trig == NULL) {
> + ret = -ENOMEM;
> + goto error_ret;
> + }
> + sigma_delta->trig->ops = &ad_sd_trigger_ops;
> + init_completion(&sigma_delta->completion);
> +
> + ret = request_irq(sigma_delta->spi->irq,
> + ad_sd_data_rdy_trig_poll,
> + IRQF_TRIGGER_LOW,
> + indio_dev->name,
> + sigma_delta);
> + if (ret)
> + goto error_free_trig;
> +
> + if (!sigma_delta->irq_dis) {
> + sigma_delta->irq_dis = true;
> + disable_irq_nosync(sigma_delta->spi->irq);
> + }
> + sigma_delta->trig->dev.parent = &sigma_delta->spi->dev;
> + sigma_delta->trig->private_data = sigma_delta;
> +
> + ret = iio_trigger_register(sigma_delta->trig);
> + if (ret)
> + goto error_free_irq;
> +
> + /* select default trigger */
> + indio_dev->trig = sigma_delta->trig;
> +
> + return 0;
> +
> +error_free_irq:
> + free_irq(sigma_delta->spi->irq, sigma_delta);
> +error_free_trig:
> + iio_trigger_free(sigma_delta->trig);
> +error_ret:
> + return ret;
> +}
> +
> +static void ad_sd_remove_trigger(struct iio_dev *indio_dev)
> +{
> + struct ad_sigma_delta *sigma_delta = iio_device_get_drvdata(indio_dev);
> +
> + iio_trigger_unregister(sigma_delta->trig);
> + free_irq(sigma_delta->spi->irq, sigma_delta);
> + iio_trigger_free(sigma_delta->trig);
> +}
> +
> +/**
> + * ad_sd_setup_buffer_and_trigger() -
> + * @indio_dev: The IIO device
> + */
> +int ad_sd_setup_buffer_and_trigger(struct iio_dev *indio_dev)
> +{
> + int ret;
> +
> + ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,
> + &ad_sd_trigger_handler, &ad_sd_buffer_setup_ops);
> + if (ret)
> + return ret;
> +
> + ret = ad_sd_probe_trigger(indio_dev);
> + if (ret) {
> + iio_triggered_buffer_cleanup(indio_dev);
> + return ret;
> + }
> +
> + return 0;
> +}
> +EXPORT_SYMBOL_GPL(ad_sd_setup_buffer_and_trigger);
> +
> +/**
> + * ad_sd_cleanup_buffer_and_trigger() -
> + * @indio_dev: The IIO device
> + */
> +void ad_sd_cleanup_buffer_and_trigger(struct iio_dev *indio_dev)
> +{
> + ad_sd_remove_trigger(indio_dev);
> + iio_triggered_buffer_cleanup(indio_dev);
> +}
> +EXPORT_SYMBOL_GPL(ad_sd_cleanup_buffer_and_trigger);
> +
> +/**
> + * ad_sd_init() - Initializes a ad_sigma_delta struct
> + * @sigma_delta: The ad_sigma_delta device
> + * @indio_dev: The IIO device which the Sigma Delta device is used for
> + * @spi: The SPI device for the ad_sigma_delta device
> + * @info: Device specific callbacks and options
> + *
> + * This function needs to be called before any other operations are performed on
> + * the ad_sigma_delta struct.
> + */
> +int ad_sd_init(struct ad_sigma_delta *sigma_delta, struct iio_dev *indio_dev,
> + struct spi_device *spi, const struct ad_sigma_delta_info *info)
> +{
> + sigma_delta->spi = spi;
> + sigma_delta->info = info;
> + iio_device_set_drvdata(indio_dev, sigma_delta);
> +
> + return 0;
> +}
> +
> +MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
> +MODULE_DESCRIPTION("Analog Devices Sigma-Delta ADCs");
> +MODULE_LICENSE("GPL v2");
> diff --git a/include/linux/iio/adc/ad_sigma_delta.h b/include/linux/iio/adc/ad_sigma_delta.h
> new file mode 100644
> index 0000000..2e4eab9
> --- /dev/null
> +++ b/include/linux/iio/adc/ad_sigma_delta.h
> @@ -0,0 +1,173 @@
> +/*
> + * Support code for Analog Devices Sigma-Delta ADCs
> + *
> + * Copyright 2012 Analog Devices Inc.
> + * Author: Lars-Peter Clausen <lars@metafoo.de>
> + *
> + * Licensed under the GPL-2.
> + */
> +#ifndef __AD_SIGMA_DELTA_H__
> +#define __AD_SIGMA_DELTA_H__
> +
> +enum ad_sigma_delta_mode {
> + AD_SD_MODE_CONTINUOUS = 0,
> + AD_SD_MODE_SINGLE = 1,
> + AD_SD_MODE_IDLE = 2,
> + AD_SD_MODE_POWERDOWN = 3,
> +};
> +
> +/**
> + * struct ad_sigma_delta_calib_data - Calibration data for Sigma Delta devices
> + * @mode: Calibration mode.
> + * @channel: Calibration channel.
> + */
> +struct ad_sd_calib_data {
> + unsigned int mode;
> + unsigned int channel;
> +};
> +
> +struct ad_sigma_delta;
> +struct iio_dev;
> +
> +/**
> + * struct ad_sigma_delta_info - Sigma Delta driver specific callbacks and options
> + * @set_channel: Will be called to select the current channel, may be NULL.
> + * @set_mode: Will be called to select the current mode, may be NULL.
> + * @postprocess_sample: Is called for each sampled data word, can be used to
> + * modify or drop the sample data, it, may be NULL.
> + * @has_registers: true if the device has writable and readable registers, false
> + * if there is just one read-only sample data shift register.
> + * @addr_shift: Shift of the register address in the communications register.
> + * @read_mask: Mask for the communications register having the read bit set.
> + */
> +struct ad_sigma_delta_info {
> + int (*set_channel)(struct ad_sigma_delta *, unsigned int channel);
> + int (*set_mode)(struct ad_sigma_delta *, enum ad_sigma_delta_mode mode);
> + int (*postprocess_sample)(struct ad_sigma_delta *, unsigned int raw_sample);
> + bool has_registers;
> + unsigned int addr_shift;
> + unsigned int read_mask;
> +};
> +
> +/**
> + * struct ad_sigma_delta - Sigma Delta device struct
> + * @spi: The spi device associated with the Sigma Delta device.
> + * @trig: The IIO trigger associated with the Sigma Delta device.
> + *
> + * Most of the fields are private to the sigma delta library code and should not
> + * be accessed by individual drivers.
> + */
> +struct ad_sigma_delta {
> + struct spi_device *spi;
> + struct iio_trigger *trig;
> +
> +/* private: */
> + struct completion completion;
> + bool irq_dis;
> +
> + bool bus_locked;
> +
> + uint8_t comm;
> +
> + const struct ad_sigma_delta_info *info;
> +
> + /*
> + * DMA (thus cache coherency maintenance) requires the
> + * transfer buffers to live in their own cache lines.
> + */
> + uint8_t data[4] ____cacheline_aligned;
> +};
> +
> +static inline int ad_sigma_delta_set_channel(struct ad_sigma_delta *sd,
> + unsigned int channel)
> +{
> + if (sd->info->set_channel)
> + return sd->info->set_channel(sd, channel);
> +
> + return 0;
> +}
> +
> +static inline int ad_sigma_delta_set_mode(struct ad_sigma_delta *sd,
> + unsigned int mode)
> +{
> + if (sd->info->set_mode)
> + return sd->info->set_mode(sd, mode);
> +
> + return 0;
> +}
> +
> +static inline int ad_sigma_delta_postprocess_sample(struct ad_sigma_delta *sd,
> + unsigned int raw_sample)
> +{
> + if (sd->info->postprocess_sample)
> + return sd->info->postprocess_sample(sd, raw_sample);
> +
> + return 0;
> +}
> +
> +void ad_sd_set_comm(struct ad_sigma_delta *sigma_delta, uint8_t comm);
> +int ad_sd_write_reg(struct ad_sigma_delta *sigma_delta, unsigned int reg,
> + unsigned int size, unsigned int val);
> +int ad_sd_read_reg(struct ad_sigma_delta *sigma_delta, unsigned int reg,
> + unsigned int size, unsigned int *val);
> +
> +int ad_sigma_delta_single_conversion(struct iio_dev *indio_dev,
> + const struct iio_chan_spec *chan, int *val);
> +int ad_sd_calibrate_all(struct ad_sigma_delta *sigma_delta,
> + const struct ad_sd_calib_data *cd, unsigned int n);
> +int ad_sd_init(struct ad_sigma_delta *sigma_delta, struct iio_dev *indio_dev,
> + struct spi_device *spi, const struct ad_sigma_delta_info *info);
> +
> +int ad_sd_setup_buffer_and_trigger(struct iio_dev *indio_dev);
> +void ad_sd_cleanup_buffer_and_trigger(struct iio_dev *indio_dev);
> +
> +int ad_sd_validate_trigger(struct iio_dev *indio_dev, struct iio_trigger *trig);
> +
> +#define __AD_SD_CHANNEL(_si, _channel1, _channel2, _address, _bits, \
> + _storagebits, _shift, _extend_name, _type) \
> + { \
> + .type = (_type), \
> + .differential = (_channel2 == -1 ? 0 : 1), \
> + .indexed = 1, \
> + .channel = (_channel1), \
> + .channel2 = (_channel2), \
> + .address = (_address), \
> + .extend_name = (_extend_name), \
> + .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
> + IIO_CHAN_INFO_SCALE_SHARED_BIT | \
> + IIO_CHAN_INFO_OFFSET_SEPARATE_BIT, \
> + .scan_index = (_si), \
> + .scan_type = { \
> + .sign = 'u', \
> + .realbits = (_bits), \
> + .storagebits = (_storagebits), \
> + .shift = (_shift), \
> + .endianness = IIO_BE, \
> + }, \
> + }
> +
> +#define AD_SD_DIFF_CHANNEL(_si, _channel1, _channel2, _address, _bits, \
> + _storagebits, _shift) \
> + __AD_SD_CHANNEL(_si, _channel1, _channel2, _address, _bits, \
> + _storagebits, _shift, NULL, IIO_VOLTAGE)
> +
> +#define AD_SD_SHORTED_CHANNEL(_si, _channel, _address, _bits, \
> + _storagebits, _shift) \
> + __AD_SD_CHANNEL(_si, _channel, _channel, _address, _bits, \
> + _storagebits, _shift, "shorted", IIO_VOLTAGE)
> +
> +#define AD_SD_CHANNEL(_si, _channel, _address, _bits, \
> + _storagebits, _shift) \
> + __AD_SD_CHANNEL(_si, _channel, -1, _address, _bits, \
> + _storagebits, _shift, NULL, IIO_VOLTAGE)
> +
> +#define AD_SD_TEMP_CHANNEL(_si, _address, _bits, _storagebits, _shift) \
> + __AD_SD_CHANNEL(_si, 0, -1, _address, _bits, \
> + _storagebits, _shift, NULL, IIO_TEMP)
> +
> +#define AD_SD_SUPPLY_CHANNEL(_si, _channel, _address, _bits, _storagebits, \
> + _shift) \
> + __AD_SD_CHANNEL(_si, _channel, -1, _address, _bits, \
> + _storagebits, _shift, "supply", IIO_VOLTAGE)
> +
> +#endif
>
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [PATCH 17/22] staging:iio:ad7780: Use common Sigma Delta library
2012-08-10 16:36 ` [PATCH 17/22] staging:iio:ad7780: Use common Sigma Delta library Lars-Peter Clausen
@ 2012-08-14 12:05 ` Jonathan Cameron
0 siblings, 0 replies; 37+ messages in thread
From: Jonathan Cameron @ 2012-08-14 12:05 UTC (permalink / raw)
To: Lars-Peter Clausen; +Cc: Jonathan Cameron, linux-iio, drivers
On 10/08/12 17:36, Lars-Peter Clausen wrote:
> Convert the ad7780 driver to make use of the new common code for devices from
> the Analog Devices Sigma Delta family.
>
> As a bonus the ad7780 driver gains support for buffered mode. Although this is a
> bit tricky. The ad7780 reports in the lower 4 unused bits of the data word the
> internal gain used. The driver will update the scale attribute value depending
> on the gain accordingly, but obviously this will only work if the gain does not
> change while sampling. This is not perfect, but since we store the raw value in
> the buffer an application which is aware of this can extract the gain factor
> from the buffer as well an apply it accordingly.
A bit ugly as you say. Given the gain is controlled by external pins,
it's probably fair to assume it won't go changing all on it's own...
In the long run we may want to think about how to encode this sort of
change in the datastream (for the few occasions where it can in theory
change out of the control of the driver...)
Anyhow, this patch looks good to me. Will pick it up later.
>
> Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
> ---
> drivers/staging/iio/adc/Kconfig | 1 +
> drivers/staging/iio/adc/ad7780.c | 186 ++++++++++++++------------------------
> 2 files changed, 71 insertions(+), 116 deletions(-)
>
> diff --git a/drivers/staging/iio/adc/Kconfig b/drivers/staging/iio/adc/Kconfig
> index 67711b7..fc7b7f6 100644
> --- a/drivers/staging/iio/adc/Kconfig
> +++ b/drivers/staging/iio/adc/Kconfig
> @@ -99,6 +99,7 @@ config AD7780
> tristate "Analog Devices AD7780 AD7781 ADC driver"
> depends on SPI
> depends on GPIOLIB
> + select AD_SIGMA_DELTA
> help
> Say yes here to build support for Analog Devices
> AD7780 and AD7781 SPI analog to digital converters (ADC).
> diff --git a/drivers/staging/iio/adc/ad7780.c b/drivers/staging/iio/adc/ad7780.c
> index 19ee49c..853f8b1 100644
> --- a/drivers/staging/iio/adc/ad7780.c
> +++ b/drivers/staging/iio/adc/ad7780.c
> @@ -20,6 +20,7 @@
>
> #include <linux/iio/iio.h>
> #include <linux/iio/sysfs.h>
> +#include <linux/iio/adc/ad_sigma_delta.h>
>
> #include "ad7780.h"
>
> @@ -37,20 +38,13 @@ struct ad7780_chip_info {
> };
>
> struct ad7780_state {
> - struct spi_device *spi;
> const struct ad7780_chip_info *chip_info;
> struct regulator *reg;
> - struct ad7780_platform_data *pdata;
> - wait_queue_head_t wq_data_avail;
> - bool done;
> + int powerdown_gpio;
> + unsigned int gain;
> u16 int_vref_mv;
> - struct spi_transfer xfer;
> - struct spi_message msg;
> - /*
> - * DMA (thus cache coherency maintenance) requires the
> - * transfer buffers to live in their own cache lines.
> - */
> - unsigned int data ____cacheline_aligned;
> +
> + struct ad_sigma_delta sd;
> };
>
> enum ad7780_supported_device_ids {
> @@ -58,28 +52,30 @@ enum ad7780_supported_device_ids {
> ID_AD7781,
> };
>
> -static int ad7780_read(struct ad7780_state *st, int *val)
> +static struct ad7780_state *ad_sigma_delta_to_ad7780(struct ad_sigma_delta *sd)
> {
> - int ret;
> -
> - spi_bus_lock(st->spi->master);
> -
> - enable_irq(st->spi->irq);
> - st->done = false;
> - gpio_set_value(st->pdata->gpio_pdrst, 1);
> + return container_of(sd, struct ad7780_state, sd);
> +}
>
> - ret = wait_event_interruptible(st->wq_data_avail, st->done);
> - disable_irq_nosync(st->spi->irq);
> - if (ret)
> - goto out;
> +static int ad7780_set_mode(struct ad_sigma_delta *sigma_delta,
> + enum ad_sigma_delta_mode mode)
> +{
> + struct ad7780_state *st = ad_sigma_delta_to_ad7780(sigma_delta);
> + unsigned val;
> +
> + switch (mode) {
> + case AD_SD_MODE_SINGLE:
> + case AD_SD_MODE_CONTINUOUS:
> + val = 1;
> + break;
> + default:
> + val = 0;
> + break;
> + }
>
> - ret = spi_sync_locked(st->spi, &st->msg);
> - *val = be32_to_cpu(st->data);
> -out:
> - gpio_set_value(st->pdata->gpio_pdrst, 0);
> - spi_bus_unlock(st->spi->master);
> + gpio_set_value(st->powerdown_gpio, val);
>
> - return ret;
> + return 0;
> }
>
> static int ad7780_read_raw(struct iio_dev *indio_dev,
> @@ -89,89 +85,57 @@ static int ad7780_read_raw(struct iio_dev *indio_dev,
> long m)
> {
> struct ad7780_state *st = iio_priv(indio_dev);
> - struct iio_chan_spec channel = st->chip_info->channel;
> - int ret, smpl = 0;
> unsigned long scale_uv;
>
> switch (m) {
> case IIO_CHAN_INFO_RAW:
> - mutex_lock(&indio_dev->mlock);
> - ret = ad7780_read(st, &smpl);
> - mutex_unlock(&indio_dev->mlock);
> -
> - if (ret < 0)
> - return ret;
> -
> - if ((smpl & AD7780_ERR) ||
> - !((smpl & AD7780_PAT0) && !(smpl & AD7780_PAT1)))
> - return -EIO;
> -
> - *val = (smpl >> channel.scan_type.shift) &
> - ((1 << (channel.scan_type.realbits)) - 1);
> - *val -= (1 << (channel.scan_type.realbits - 1));
> -
> - if (!(smpl & AD7780_GAIN))
> - *val *= 128;
> -
> - return IIO_VAL_INT;
> + return ad_sigma_delta_single_conversion(indio_dev, chan, val);
> case IIO_CHAN_INFO_SCALE:
> - scale_uv = (st->int_vref_mv * 100000)
> - >> (channel.scan_type.realbits - 1);
> + scale_uv = (st->int_vref_mv * 100000 * st->gain)
> + >> (chan->scan_type.realbits - 1);
> *val = scale_uv / 100000;
> *val2 = (scale_uv % 100000) * 10;
> return IIO_VAL_INT_PLUS_MICRO;
> + case IIO_CHAN_INFO_OFFSET:
> + *val -= (1 << (chan->scan_type.realbits - 1));
> + return IIO_VAL_INT;
> }
> +
> return -EINVAL;
> }
>
> +static int ad7780_postprocess_sample(struct ad_sigma_delta *sigma_delta,
> + unsigned int raw_sample)
> +{
> + struct ad7780_state *st = ad_sigma_delta_to_ad7780(sigma_delta);
> +
> + if ((raw_sample & AD7780_ERR) ||
> + !((raw_sample & AD7780_PAT0) && !(raw_sample & AD7780_PAT1)))
> + return -EIO;
> +
> + if (raw_sample & AD7780_GAIN)
> + st->gain = 1;
> + else
> + st->gain = 128;
> +
> + return 0;
> +}
> +
> +static const struct ad_sigma_delta_info ad7780_sigma_delta_info = {
> + .set_mode = ad7780_set_mode,
> + .postprocess_sample = ad7780_postprocess_sample,
> + .has_registers = false,
> +};
> +
> static const struct ad7780_chip_info ad7780_chip_info_tbl[] = {
> [ID_AD7780] = {
> - .channel = {
> - .type = IIO_VOLTAGE,
> - .indexed = 1,
> - .channel = 0,
> - .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
> - IIO_CHAN_INFO_SCALE_SHARED_BIT |
> - IIO_CHAN_INFO_OFFSET_SHARED_BIT,
> - .scan_type = {
> - .sign = 'u',
> - .realbits = 24,
> - .storagebits = 32,
> - .shift = 8,
> - },
> - },
> + .channel = AD_SD_CHANNEL(1, 0, 0, 24, 32, 8),
> },
> [ID_AD7781] = {
> - .channel = {
> - .type = IIO_VOLTAGE,
> - .indexed = 1,
> - .channel = 0,
> - .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
> - IIO_CHAN_INFO_SCALE_SHARED_BIT |
> - IIO_CHAN_INFO_OFFSET_SHARED_BIT,
> - .scan_type = {
> - .sign = 'u',
> - .realbits = 20,
> - .storagebits = 32,
> - .shift = 12,
> - },
> - },
> + .channel = AD_SD_CHANNEL(1, 0, 0, 20, 32, 12),
> },
> };
>
> -/**
> - * Interrupt handler
> - */
> -static irqreturn_t ad7780_interrupt(int irq, void *dev_id)
> -{
> - struct ad7780_state *st = dev_id;
> -
> - st->done = true;
> - wake_up_interruptible(&st->wq_data_avail);
> -
> - return IRQ_HANDLED;
> -};
> -
> static const struct iio_info ad7780_info = {
> .read_raw = &ad7780_read_raw,
> .driver_module = THIS_MODULE,
> @@ -194,6 +158,9 @@ static int __devinit ad7780_probe(struct spi_device *spi)
> return -ENOMEM;
>
> st = iio_priv(indio_dev);
> + st->gain = 1;
> +
> + ad_sd_init(&st->sd, indio_dev, spi, &ad7780_sigma_delta_info);
>
> st->reg = regulator_get(&spi->dev, "vcc");
> if (!IS_ERR(st->reg)) {
> @@ -207,7 +174,7 @@ static int __devinit ad7780_probe(struct spi_device *spi)
> st->chip_info =
> &ad7780_chip_info_tbl[spi_get_device_id(spi)->driver_data];
>
> - st->pdata = pdata;
> + st->powerdown_gpio = pdata->gpio_pdrst;
>
> if (pdata && pdata->vref_mv)
> st->int_vref_mv = pdata->vref_mv;
> @@ -217,7 +184,6 @@ static int __devinit ad7780_probe(struct spi_device *spi)
> dev_warn(&spi->dev, "reference voltage unspecified\n");
>
> spi_set_drvdata(spi, indio_dev);
> - st->spi = spi;
>
> indio_dev->dev.parent = &spi->dev;
> indio_dev->name = spi_get_device_id(spi)->name;
> @@ -226,40 +192,27 @@ static int __devinit ad7780_probe(struct spi_device *spi)
> indio_dev->num_channels = 1;
> indio_dev->info = &ad7780_info;
>
> - init_waitqueue_head(&st->wq_data_avail);
> -
> - /* Setup default message */
> -
> - st->xfer.rx_buf = &st->data;
> - st->xfer.len = st->chip_info->channel.scan_type.storagebits / 8;
> -
> - spi_message_init(&st->msg);
> - spi_message_add_tail(&st->xfer, &st->msg);
> -
> - ret = gpio_request_one(st->pdata->gpio_pdrst, GPIOF_OUT_INIT_LOW,
> + ret = gpio_request_one(pdata->gpio_pdrst, GPIOF_OUT_INIT_LOW,
> "AD7780 /PDRST");
> if (ret) {
> dev_err(&spi->dev, "failed to request GPIO PDRST\n");
> goto error_disable_reg;
> }
>
> - ret = request_irq(spi->irq, ad7780_interrupt,
> - IRQF_TRIGGER_FALLING, spi_get_device_id(spi)->name, st);
> + ret = ad_sd_setup_buffer_and_trigger(indio_dev);
> if (ret)
> goto error_free_gpio;
>
> - disable_irq(spi->irq);
> -
> ret = iio_device_register(indio_dev);
> if (ret)
> - goto error_free_irq;
> + goto error_cleanup_buffer_and_trigger;
>
> return 0;
>
> -error_free_irq:
> - free_irq(spi->irq, st);
> +error_cleanup_buffer_and_trigger:
> + ad_sd_cleanup_buffer_and_trigger(indio_dev);
> error_free_gpio:
> - gpio_free(st->pdata->gpio_pdrst);
> + gpio_free(pdata->gpio_pdrst);
> error_disable_reg:
> if (!IS_ERR(st->reg))
> regulator_disable(st->reg);
> @@ -278,8 +231,9 @@ static int ad7780_remove(struct spi_device *spi)
> struct ad7780_state *st = iio_priv(indio_dev);
>
> iio_device_unregister(indio_dev);
> - free_irq(spi->irq, st);
> - gpio_free(st->pdata->gpio_pdrst);
> + ad_sd_cleanup_buffer_and_trigger(indio_dev);
> +
> + gpio_free(st->powerdown_gpio);
> if (!IS_ERR(st->reg)) {
> regulator_disable(st->reg);
> regulator_put(st->reg);
>
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [PATCH 07/22] staging:iio:ad7793: Remove unused platform_data from device state struct
2012-08-10 16:36 ` [PATCH 07/22] staging:iio:ad7793: Remove unused platform_data from device state struct Lars-Peter Clausen
@ 2012-08-14 19:39 ` Jonathan Cameron
2012-08-14 20:19 ` Jonathan Cameron
[not found] ` <502B6688.6000904@metafoo.de>
0 siblings, 2 replies; 37+ messages in thread
From: Jonathan Cameron @ 2012-08-14 19:39 UTC (permalink / raw)
To: Lars-Peter Clausen; +Cc: Jonathan Cameron, linux-iio, drivers
On 08/10/2012 05:36 PM, Lars-Peter Clausen wrote:
> The platform data for the device is only used from within the drivers probe
> callback, so there is no need to keep it around in the devices state struct.
>
> While we are at it mark the platform data struct as const.
>
> Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
> ---
> drivers/staging/iio/adc/ad7793.c | 14 ++++++--------
> 1 file changed, 6 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/staging/iio/adc/ad7793.c b/drivers/staging/iio/adc/ad7793.c
> index 112e2b7..0ba598e 100644
> --- a/drivers/staging/iio/adc/ad7793.c
> +++ b/drivers/staging/iio/adc/ad7793.c
> @@ -44,7 +44,6 @@ struct ad7793_state {
> struct iio_trigger *trig;
> const struct ad7793_chip_info *chip_info;
> struct regulator *reg;
> - struct ad7793_platform_data *pdata;
> wait_queue_head_t wq_data_avail;
> bool done;
> bool irq_dis;
> @@ -253,7 +252,8 @@ out:
> return ret;
> }
>
> -static int ad7793_setup(struct ad7793_state *st)
> +static int ad7793_setup(struct ad7793_state *st
> + const struct ad7793_platform_data *pdata)
Really odd. There's a missing comma between the arguments here...
I'll fixup.
> {
> int i, ret = -1;
> unsigned long long scale_uv;
> @@ -277,9 +277,9 @@ static int ad7793_setup(struct ad7793_state *st)
> goto out;
> }
>
> - st->mode = (st->pdata->mode & ~AD7793_MODE_SEL(-1)) |
> + st->mode = (pdata->mode & ~AD7793_MODE_SEL(-1)) |
> AD7793_MODE_SEL(AD7793_MODE_IDLE);
> - st->conf = st->pdata->conf & ~AD7793_CONF_CHAN(-1);
> + st->conf = pdata->conf & ~AD7793_CONF_CHAN(-1);
>
> ret = ad7793_write_reg(st, AD7793_REG_MODE, sizeof(st->mode), st->mode);
> if (ret)
> @@ -882,7 +882,7 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = {
>
> static int __devinit ad7793_probe(struct spi_device *spi)
> {
> - struct ad7793_platform_data *pdata = spi->dev.platform_data;
> + const struct ad7793_platform_data *pdata = spi->dev.platform_data;
> struct ad7793_state *st;
> struct iio_dev *indio_dev;
> int ret, voltage_uv = 0;
> @@ -915,8 +915,6 @@ static int __devinit ad7793_probe(struct spi_device *spi)
> st->chip_info =
> &ad7793_chip_info_tbl[spi_get_device_id(spi)->driver_data];
>
> - st->pdata = pdata;
> -
> if (pdata && pdata->vref_mv)
> st->int_vref_mv = pdata->vref_mv;
> else if (voltage_uv)
> @@ -944,7 +942,7 @@ static int __devinit ad7793_probe(struct spi_device *spi)
> if (ret)
> goto error_unreg_ring;
>
> - ret = ad7793_setup(st);
> + ret = ad7793_setup(st, pdata);
> if (ret)
> goto error_remove_trigger;
>
>
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [PATCH 22/22] staging:iio:adc: Add AD7791 driver
2012-08-13 13:12 ` Lars-Peter Clausen
@ 2012-08-14 20:18 ` Jonathan Cameron
0 siblings, 0 replies; 37+ messages in thread
From: Jonathan Cameron @ 2012-08-14 20:18 UTC (permalink / raw)
To: Lars-Peter Clausen; +Cc: Jonathan Cameron, linux-iio, drivers
On 08/13/2012 02:12 PM, Lars-Peter Clausen wrote:
> On 08/10/2012 06:36 PM, Lars-Peter Clausen wrote:
>> This patch adds support for the Analog Devices AD7787, AD7788, AD7789, AD7790
>> and AD7791 Sigma Delta Analog-to-Digital converters.
>>
>> Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
>> ---
>> [...]
>> + case IIO_CHAN_INFO_SCALE:
>> + /* The monitor channel uses an internal reference. */
>> + if (chan->address == AD7791_CH_AVDD_MONITOR) {
>> + scale_nv = 5850000000ULL;
>> + } else {
>> + int voltage_uv;
>> +
>> + voltage_uv = regulator_get_voltage(st->reg);
>> + if (voltage_uv < 0)
>> + return voltage_uv;
>> + scale_nv = voltage_uv * 1000;
>> + }
>> + if (unipolar)
>> + scale_nv >>= chan->scan_type.realbits;
>> + else
>> + scale_nv >>= chan->scan_type.realbits - 1;
>> + *val2 = do_div(scale_nv, 1000000);
>> + *val = scale_nv;
>> +
>
> Just noticed that the scale is off by a factor of 1000. It reports volts
> while we want milli volts.
I'll definitely ignore this driver for now then :)
>
>> + return IIO_VAL_INT_PLUS_NANO;
>> + }
>
>
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [PATCH 16/22] iio:adc: Add common code for ADI Sigma Delta devices
2012-08-10 16:36 ` [PATCH 16/22] iio:adc: Add common code for ADI Sigma Delta devices Lars-Peter Clausen
2012-08-14 12:03 ` Jonathan Cameron
@ 2012-08-14 20:19 ` Jonathan Cameron
1 sibling, 0 replies; 37+ messages in thread
From: Jonathan Cameron @ 2012-08-14 20:19 UTC (permalink / raw)
To: Lars-Peter Clausen; +Cc: Jonathan Cameron, linux-iio, drivers
On 08/10/2012 05:36 PM, Lars-Peter Clausen wrote:
> Most devices from the Analog Devices Sigma Delta family use a similar scheme for
> communication with the device. This includes register access, as well as trigger
> handling. But each device sub-family has different features and different
> register layouts (some even have no registers at all) and thus it is impractical
> to try to support all of the devices by the same driver. This patch adds a
> common base library for Sigma Delta converter devices. It will be used by
> individual drivers.
>
> This code is mostly based on the three existing Sigma Delta drivers the AD7192,
> AD7780 and AD7793, but has been improved for more robustness and flexibility.
>
Lars-Peter.
One obvious bug below. I've fixed this up too, please verify the fixed version
in the togreg-postfixes branch.
> Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
> ---
> drivers/iio/adc/Kconfig | 5 +
> drivers/iio/adc/Makefile | 1 +
> drivers/iio/adc/ad_sigma_delta.c | 557 ++++++++++++++++++++++++++++++++
> include/linux/iio/adc/ad_sigma_delta.h | 173 ++++++++++
> 4 files changed, 736 insertions(+)
> create mode 100644 drivers/iio/adc/ad_sigma_delta.c
> create mode 100644 include/linux/iio/adc/ad_sigma_delta.h
>
> diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
> index 8a78b4f..a2c5071 100644
> --- a/drivers/iio/adc/Kconfig
> +++ b/drivers/iio/adc/Kconfig
> @@ -3,6 +3,11 @@
> #
> menu "Analog to digital converters"
>
> +config AD_SIGMA_DELTA
> + tristate
> + select IIO_BUFFER
> + select IIO_TRIGGERED_BUFFER
> +
> config AD7266
> tristate "Analog Devices AD7265/AD7266 ADC driver"
> depends on SPI_MASTER
> diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
> index 52eec25..5989356 100644
> --- a/drivers/iio/adc/Makefile
> +++ b/drivers/iio/adc/Makefile
> @@ -2,5 +2,6 @@
> # Makefile for IIO ADC drivers
> #
>
> +obj-$(CONFIG_AD_SIGMA_DELTA) += ad_sigma_delta.o
> obj-$(CONFIG_AD7266) += ad7266.o
> obj-$(CONFIG_AT91_ADC) += at91_adc.o
> diff --git a/drivers/iio/adc/ad_sigma_delta.c b/drivers/iio/adc/ad_sigma_delta.c
> new file mode 100644
> index 0000000..555feb7
> --- /dev/null
> +++ b/drivers/iio/adc/ad_sigma_delta.c
> @@ -0,0 +1,557 @@
> +/*
> + * Support code for Analog Devices Sigma-Delta ADCs
> + *
> + * Copyright 2012 Analog Devices Inc.
> + * Author: Lars-Peter Clausen <lars@metafoo.de>
> + *
> + * Licensed under the GPL-2.
> + */
> +
> +#include <linux/interrupt.h>
> +#include <linux/device.h>
> +#include <linux/kernel.h>
> +#include <linux/slab.h>
> +#include <linux/spi/spi.h>
> +#include <linux/err.h>
> +#include <linux/module.h>
> +
> +#include <linux/iio/iio.h>
> +#include <linux/iio/sysfs.h>
> +#include <linux/iio/buffer.h>
> +#include <linux/iio/trigger.h>
> +#include <linux/iio/trigger_consumer.h>
> +#include <linux/iio/triggered_buffer.h>
> +#include <linux/iio/adc/ad_sigma_delta.h>
> +
> +#include <asm/unaligned.h>
> +
> +
> +#define AD_SD_COMM_CHAN_MASK 0x3
> +
> +#define AD_SD_REG_COMM 0x00
> +#define AD_SD_REG_DATA 0x03
> +
> +/**
> + * ad_sd_set_comm() - Set communications register
> + *
> + * @sigma_delta: The sigma delta device
> + * @comm: New value for the communications register
> + */
> +void ad_sd_set_comm(struct ad_sigma_delta *sigma_delta, uint8_t comm)
> +{
> + /* Some variants use the lower two bits of the communications register
> + * to select the channel */
> + sigma_delta->comm = comm & AD_SD_COMM_CHAN_MASK;
> +}
> +EXPORT_SYMBOL_GPL(ad_sd_set_comm);
> +
> +/**
> + * ad_sd_write_reg() - Write a register
> + *
> + * @sigma_delta: The sigma delta device
> + * @reg: Address of the register
> + * @size: Size of the register (0-3)
> + * @val: Value to write to the register
> + *
> + * Returns 0 on success, an error code otherwise.
> + **/
> +int ad_sd_write_reg(struct ad_sigma_delta *sigma_delta, unsigned int reg,
> + unsigned int size, unsigned int val)
> +{
> + uint8_t *data = sigma_delta->data;
> + struct spi_transfer t = {
> + .tx_buf = data,
> + .len = size + 1,
> + .cs_change = sigma_delta->bus_locked,
> + };
> + struct spi_message m;
> + int ret;
> +
> + data[0] = (reg << sigma_delta->info->addr_shift) | sigma_delta->comm;
> +
> + switch (size) {
> + case 3:
> + data[1] = val >> 16;
> + data[2] = val >> 8;
> + data[3] = val;
> + break;
> + case 2:
> + put_unaligned_be16(val, &data[1]);
> + break;
> + case 1:
> + data[1] = val;
> + break;
> + case 0:
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + spi_message_init(&m);
> + spi_message_add_tail(&t, &m);
> +
> + if (sigma_delta->bus_locked)
> + ret = spi_sync_locked(sigma_delta->spi, &m);
> + else
> + ret = spi_sync(sigma_delta->spi, &m);
> +
> + return ret;
> +}
> +EXPORT_SYMBOL_GPL(ad_sd_write_reg);
> +
> +static int ad_sd_read_reg_raw(struct ad_sigma_delta *sigma_delta,
> + unsigned int reg, unsigned int size, uint8_t *val)
> +{
> + uint8_t *data = sigma_delta->data;
> + int ret;
> + struct spi_transfer t[] = {
> + {
> + .tx_buf = data,
> + .len = 1,
> + }, {
> + .rx_buf = val,
> + .len = size,
> + .cs_change = sigma_delta->bus_locked,
> + },
> + };
> + struct spi_message m;
> +
> + spi_message_init(&m);
> +
> + if (sigma_delta->info->has_registers) {
> + data[0] = reg << sigma_delta->info->addr_shift;
> + data[0] |= sigma_delta->info->read_mask;
> + spi_message_add_tail(&t[0], &m);
> + }
> + spi_message_add_tail(&t[1], &m);
> +
> + if (sigma_delta->bus_locked)
> + ret = spi_sync_locked(sigma_delta->spi, &m);
> + else
> + ret = spi_sync(sigma_delta->spi, &m);
> +
> + return ret;
> +}
> +
> +/**
> + * ad_sd_read_reg() - Read a register
> + *
> + * @sigma_delta: The sigma delta device
> + * @reg: Address of the register
> + * @size: Size of the register (1-4)
> + * @val: Read value
> + *
> + * Returns 0 on success, an error code otherwise.
> + **/
> +int ad_sd_read_reg(struct ad_sigma_delta *sigma_delta,
> + unsigned int reg, unsigned int size, unsigned int *val)
> +{
> + int ret;
> +
> + ret = ad_sd_read_reg_raw(sigma_delta, reg, size, sigma_delta->data);
> + if (ret < 0)
> + goto out;
> +
> + switch (size) {
> + case 4:
> + *val = get_unaligned_be32(sigma_delta->data);
> + break;
> + case 3:
> + *val = (sigma_delta->data[0] << 16) |
> + (sigma_delta->data[1] << 8) |
> + sigma_delta->data[2];
> + break;
> + case 2:
> + *val = get_unaligned_be16(sigma_delta->data);
> + break;
> + case 1:
> + *val = sigma_delta->data[0];
> + break;
> + default:
> + ret = -EINVAL;
> + break;
> + }
> +
> +out:
> + return ret;
> +}
> +EXPORT_SYMBOL_GPL(ad_sd_read_reg);
> +
> +static int ad_sd_calibrate(struct ad_sigma_delta *sigma_delta,
> + unsigned int mode, unsigned int channel)
> +{
> + int ret;
> +
> + ret = ad_sigma_delta_set_channel(sigma_delta, channel);
> + if (ret)
> + return ret;
> +
> + spi_bus_lock(sigma_delta->spi->master);
> + sigma_delta->bus_locked = true;
> + INIT_COMPLETION(sigma_delta->completion);
> +
> + ret = ad_sigma_delta_set_mode(sigma_delta, mode);
> + if (ret < 0)
> + goto out;
> +
> + sigma_delta->irq_dis = false;
> + enable_irq(sigma_delta->spi->irq);
> + ret = wait_for_completion_timeout(&sigma_delta->completion, 2*HZ);
> + if (ret == 0) {
> + sigma_delta->irq_dis = true;
> + disable_irq_nosync(sigma_delta->spi->irq);
> + ret = -EIO;
> + } else {
> + ret = 0;
> + }
> +out:
> + sigma_delta->bus_locked = false;
> + spi_bus_unlock(sigma_delta->spi->master);
> + ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_IDLE);
> +
> + return ret;
> +}
> +
> +/**
> + * ad_sd_calibrate_all() - Performs channel calibration
> + * @sigma_delta: The sigma delta device
> + * @cb: Array of channels and calibration type to perform
> + * @n: Number of items in cb
> + *
> + * Returns 0 on success, an error code otherwise.
> + **/
> +int ad_sd_calibrate_all(struct ad_sigma_delta *sigma_delta,
> + const struct ad_sd_calib_data *cb, unsigned int n)
> +{
> + unsigned int i;
> + int ret;
> +
> + for (i = 0; i < n; i++) {
> + ret = ad_sd_calibrate(sigma_delta, cb[i].mode, cb[i].channel);
> + if (ret)
> + return ret;
> + }
> +
> + return 0;
> +}
> +EXPORT_SYMBOL_GPL(ad_sd_calibrate_all);
> +
> +/**
> + * ad_sigma_delta_single_conversion() - Performs a single data conversion
> + * @indio_dev: The IIO device
> + * @chan: The conversion is done for this channel
> + * @val: Pointer to the location where to store the read value
> + *
> + * Returns: 0 on success, an error value otherwise.
> + */
> +int ad_sigma_delta_single_conversion(struct iio_dev *indio_dev,
> + const struct iio_chan_spec *chan, int *val)
> +{
> + struct ad_sigma_delta *sigma_delta = iio_device_get_drvdata(indio_dev);
> + unsigned int sample, raw_sample;
> + int ret = 0;
> +
> + if (iio_buffer_enabled(indio_dev))
> + return -EBUSY;
> +
> + mutex_lock(&indio_dev->mlock);
> + ad_sigma_delta_set_channel(sigma_delta, chan->address);
> +
> + spi_bus_lock(sigma_delta->spi->master);
> + sigma_delta->bus_locked = true;
> + INIT_COMPLETION(sigma_delta->completion);
> +
> + ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_SINGLE);
> +
> + sigma_delta->irq_dis = false;
> + enable_irq(sigma_delta->spi->irq);
> + ret = wait_for_completion_interruptible_timeout(
> + &sigma_delta->completion, HZ);
> +
> + sigma_delta->bus_locked = false;
> + spi_bus_unlock(sigma_delta->spi->master);
> +
> + if (ret == 0)
> + ret = -EIO;
> + if (ret < 0)
> + goto out;
> +
> + ret = ad_sd_read_reg(sigma_delta, AD_SD_REG_DATA,
> + DIV_ROUND_UP(chan->scan_type.realbits + chan->scan_type.shift, 8),
> + &raw_sample);
> +
> +out:
> + if (!sigma_delta->irq_dis) {
> + disable_irq_nosync(sigma_delta->spi->irq);
> + sigma_delta->irq_dis = true;
> + }
> +
> + ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_IDLE);
> + mutex_unlock(&indio_dev->mlock);
> +
> + if (ret)
> + return ret;
> +
> + sample = raw_sample >> chan->scan_type.shift;
> + sample &= (1 << chan->scan_type.realbits) - 1;
> + *val = sample;
> +
> + ret = ad_sigma_delta_postprocess_sample(sigma_delta, raw_sample);
> + if (ret)
> + return ret;
> +
> + return IIO_VAL_INT;
> +}
> +EXPORT_SYMBOL_GPL(ad_sigma_delta_single_conversion);
> +
> +static int ad_sd_buffer_postenable(struct iio_dev *indio_dev)
> +{
> + struct ad_sigma_delta *sigma_delta = iio_device_get_drvdata(indio_dev);
> + unsigned int channel;
> + int ret;
> +
> + ret = iio_triggered_buffer_postenable(indio_dev);
> + if (ret < 0)
> + return ret;
> +
> + channel = find_first_bit(indio_dev->active_scan_mask,
> + indio_dev->masklength);
> + ret = ad_sigma_delta_set_channel(sigma_delta,
> + indio_dev->channels[channel].address);
> + if (ret)
> + goto err_predisable;
> +
> + spi_bus_lock(sigma_delta->spi->master);
> + sigma_delta->bus_locked = true;
> + ret = ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_CONTINUOUS);
> + if (ret)
> + goto err_unlock;
> +
> + sigma_delta->irq_dis = false;
> + enable_irq(sigma_delta->spi->irq);
> +
> + return 0;
> +
> +err_unlock:
> + spi_bus_unlock(sigma_delta->spi->master);
> +err_predisable:
> +
> + return ret;
> +}
> +
> +static int ad_sd_buffer_postdisable(struct iio_dev *indio_dev)
> +{
> + struct ad_sigma_delta *sigma_delta = iio_device_get_drvdata(indio_dev);
> +
> + INIT_COMPLETION(sigma_delta->completion);
> + wait_for_completion_timeout(&sigma_delta->completion, HZ);
> +
> + if (!sigma_delta->irq_dis) {
> + disable_irq_nosync(sigma_delta->spi->irq);
> + sigma_delta->irq_dis = true;
> + }
> +
> + ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_IDLE);
> +
> + sigma_delta->bus_locked = false;
> + return spi_bus_unlock(sigma_delta->spi->master);
> +}
> +
> +static irqreturn_t ad_sd_trigger_handler(int irq, void *p)
> +{
> + struct iio_poll_func *pf = p;
> + struct iio_dev *indio_dev = pf->indio_dev;
> + struct ad_sigma_delta *sigma_delta = iio_device_get_drvdata(indio_dev);
> + unsigned int reg_size;
> + uint8_t data[16];
> + int ret;
> +
> + memset(data, 0x00, 16);
> +
> + /* Guaranteed to be aligned with 8 byte boundary */
> + if (indio_dev->scan_timestamp)
> + ((s64 *)data)[1] = pf->timestamp;
> +
> + reg_size = indio_dev->channels[0].scan_type.realbits +
> + indio_dev->channels[0].scan_type.shift;
> + reg_size = DIV_ROUND_UP(reg_size, 8);
> +
> + switch (reg_size) {
> + case 4:
> + case 2:
> + case 1:
> + ret = ad_sd_read_reg_raw(sigma_delta, AD_SD_REG_DATA,
> + reg_size, &data[0]);
> + break;
> + case 3:
> + /* We store 24 bit samples in a 32 bit word. Keep the upper
> + * byte set to zero. */
> + ret = ad_sd_read_reg_raw(sigma_delta, AD_SD_REG_DATA,
> + reg_size, &data[1]);
> + break;
> + }
> +
> + iio_push_to_buffer(indio_dev->buffer, (uint8_t *)data, pf->timestamp);
> +
> + iio_trigger_notify_done(indio_dev->trig);
> + sigma_delta->irq_dis = false;
> + enable_irq(sigma_delta->spi->irq);
> +
> + return IRQ_HANDLED;
> +}
> +
> +static const struct iio_buffer_setup_ops ad_sd_buffer_setup_ops = {
> + .preenable = &iio_sw_buffer_preenable,
> + .postenable = &ad_sd_buffer_postenable,
> + .predisable = &iio_triggered_buffer_predisable,
> + .postdisable = &ad_sd_buffer_postdisable,
> + .validate_scan_mask = &iio_validate_scan_mask_onehot,
> +};
> +
> +static irqreturn_t ad_sd_data_rdy_trig_poll(int irq, void *private)
> +{
> + struct ad_sigma_delta *sigma_delta = private;
> +
> + complete(&sigma_delta->completion);
> + disable_irq_nosync(irq);
> + sigma_delta->irq_dis = true;
> + iio_trigger_poll(sigma_delta->trig, iio_get_time_ns());
> +
> + return IRQ_HANDLED;
> +}
> +
> +/**
> + * ad_sd_validate_trigger() - validate_trigger callback for ad_sigma_delta devices
> + * @indio_dev: The IIO device
> + * @trig: The new trigger
> + *
> + * Returns: 0 if the 'trig' matches the trigger registered by the ad_sigma_delta
> + * device, -EINVAL otherwise.
> + */
> +int ad_sd_validate_trigger(struct iio_dev *indio_dev, struct iio_trigger *trig)
> +{
> + struct ad_sigma_delta *sigma_delta = iio_device_get_drvdata(indio_dev);
> +
> + if (sigma_delta->trig != trig)
> + return -EINVAL;
> +
> + return 0;
> +}
> +EXPORT_SYMBOL_GPL(ad_sd_validate_trigger);
> +
> +static const struct iio_trigger_ops ad_sd_trigger_ops = {
> + .owner = THIS_MODULE,
> +};
> +
> +static int ad_sd_probe_trigger(struct iio_dev *indio_dev)
> +{
> + struct ad_sigma_delta *sigma_delta = iio_device_get_drvdata(indio_dev);
> + int ret;
> +
> + sigma_delta->trig = iio_trigger_alloc("%s-dev%d", indio_dev->name,
> + indio_dev->id);
> + if (sigma_delta->trig == NULL) {
> + ret = -ENOMEM;
> + goto error_ret;
> + }
> + sigma_delta->trig->ops = &ad_sd_trigger_ops;
> + init_completion(&sigma_delta->completion);
> +
> + ret = request_irq(sigma_delta->spi->irq,
> + ad_sd_data_rdy_trig_poll,
> + IRQF_TRIGGER_LOW,
> + indio_dev->name,
> + sigma_delta);
> + if (ret)
> + goto error_free_trig;
> +
> + if (!sigma_delta->irq_dis) {
> + sigma_delta->irq_dis = true;
> + disable_irq_nosync(sigma_delta->spi->irq);
> + }
> + sigma_delta->trig->dev.parent = &sigma_delta->spi->dev;
> + sigma_delta->trig->private_data = sigma_delta;
> +
> + ret = iio_trigger_register(sigma_delta->trig);
> + if (ret)
> + goto error_free_irq;
> +
> + /* select default trigger */
> + indio_dev->trig = sigma_delta->trig;
> +
> + return 0;
> +
> +error_free_irq:
> + free_irq(sigma_delta->spi->irq, sigma_delta);
> +error_free_trig:
> + iio_trigger_free(sigma_delta->trig);
> +error_ret:
> + return ret;
> +}
> +
> +static void ad_sd_remove_trigger(struct iio_dev *indio_dev)
> +{
> + struct ad_sigma_delta *sigma_delta = iio_device_get_drvdata(indio_dev);
> +
> + iio_trigger_unregister(sigma_delta->trig);
> + free_irq(sigma_delta->spi->irq, sigma_delta);
> + iio_trigger_free(sigma_delta->trig);
> +}
> +
> +/**
> + * ad_sd_setup_buffer_and_trigger() -
> + * @indio_dev: The IIO device
> + */
> +int ad_sd_setup_buffer_and_trigger(struct iio_dev *indio_dev)
> +{
> + int ret;
> +
> + ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,
> + &ad_sd_trigger_handler, &ad_sd_buffer_setup_ops);
> + if (ret)
> + return ret;
> +
> + ret = ad_sd_probe_trigger(indio_dev);
> + if (ret) {
> + iio_triggered_buffer_cleanup(indio_dev);
> + return ret;
> + }
> +
> + return 0;
> +}
> +EXPORT_SYMBOL_GPL(ad_sd_setup_buffer_and_trigger);
> +
> +/**
> + * ad_sd_cleanup_buffer_and_trigger() -
> + * @indio_dev: The IIO device
> + */
> +void ad_sd_cleanup_buffer_and_trigger(struct iio_dev *indio_dev)
> +{
> + ad_sd_remove_trigger(indio_dev);
> + iio_triggered_buffer_cleanup(indio_dev);
> +}
> +EXPORT_SYMBOL_GPL(ad_sd_cleanup_buffer_and_trigger);
> +
> +/**
> + * ad_sd_init() - Initializes a ad_sigma_delta struct
> + * @sigma_delta: The ad_sigma_delta device
> + * @indio_dev: The IIO device which the Sigma Delta device is used for
> + * @spi: The SPI device for the ad_sigma_delta device
> + * @info: Device specific callbacks and options
> + *
> + * This function needs to be called before any other operations are performed on
> + * the ad_sigma_delta struct.
> + */
> +int ad_sd_init(struct ad_sigma_delta *sigma_delta, struct iio_dev *indio_dev,
> + struct spi_device *spi, const struct ad_sigma_delta_info *info)
> +{
> + sigma_delta->spi = spi;
> + sigma_delta->info = info;
> + iio_device_set_drvdata(indio_dev, sigma_delta);
> +
> + return 0;
> +}
EXPORT_SYMBOL_GPL(ad_sd_init);
> +
> +MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
> +MODULE_DESCRIPTION("Analog Devices Sigma-Delta ADCs");
> +MODULE_LICENSE("GPL v2");
> diff --git a/include/linux/iio/adc/ad_sigma_delta.h b/include/linux/iio/adc/ad_sigma_delta.h
> new file mode 100644
> index 0000000..2e4eab9
> --- /dev/null
> +++ b/include/linux/iio/adc/ad_sigma_delta.h
> @@ -0,0 +1,173 @@
> +/*
> + * Support code for Analog Devices Sigma-Delta ADCs
> + *
> + * Copyright 2012 Analog Devices Inc.
> + * Author: Lars-Peter Clausen <lars@metafoo.de>
> + *
> + * Licensed under the GPL-2.
> + */
> +#ifndef __AD_SIGMA_DELTA_H__
> +#define __AD_SIGMA_DELTA_H__
> +
> +enum ad_sigma_delta_mode {
> + AD_SD_MODE_CONTINUOUS = 0,
> + AD_SD_MODE_SINGLE = 1,
> + AD_SD_MODE_IDLE = 2,
> + AD_SD_MODE_POWERDOWN = 3,
> +};
> +
> +/**
> + * struct ad_sigma_delta_calib_data - Calibration data for Sigma Delta devices
> + * @mode: Calibration mode.
> + * @channel: Calibration channel.
> + */
> +struct ad_sd_calib_data {
> + unsigned int mode;
> + unsigned int channel;
> +};
> +
> +struct ad_sigma_delta;
> +struct iio_dev;
> +
> +/**
> + * struct ad_sigma_delta_info - Sigma Delta driver specific callbacks and options
> + * @set_channel: Will be called to select the current channel, may be NULL.
> + * @set_mode: Will be called to select the current mode, may be NULL.
> + * @postprocess_sample: Is called for each sampled data word, can be used to
> + * modify or drop the sample data, it, may be NULL.
> + * @has_registers: true if the device has writable and readable registers, false
> + * if there is just one read-only sample data shift register.
> + * @addr_shift: Shift of the register address in the communications register.
> + * @read_mask: Mask for the communications register having the read bit set.
> + */
> +struct ad_sigma_delta_info {
> + int (*set_channel)(struct ad_sigma_delta *, unsigned int channel);
> + int (*set_mode)(struct ad_sigma_delta *, enum ad_sigma_delta_mode mode);
> + int (*postprocess_sample)(struct ad_sigma_delta *, unsigned int raw_sample);
> + bool has_registers;
> + unsigned int addr_shift;
> + unsigned int read_mask;
> +};
> +
> +/**
> + * struct ad_sigma_delta - Sigma Delta device struct
> + * @spi: The spi device associated with the Sigma Delta device.
> + * @trig: The IIO trigger associated with the Sigma Delta device.
> + *
> + * Most of the fields are private to the sigma delta library code and should not
> + * be accessed by individual drivers.
> + */
> +struct ad_sigma_delta {
> + struct spi_device *spi;
> + struct iio_trigger *trig;
> +
> +/* private: */
> + struct completion completion;
> + bool irq_dis;
> +
> + bool bus_locked;
> +
> + uint8_t comm;
> +
> + const struct ad_sigma_delta_info *info;
> +
> + /*
> + * DMA (thus cache coherency maintenance) requires the
> + * transfer buffers to live in their own cache lines.
> + */
> + uint8_t data[4] ____cacheline_aligned;
> +};
> +
> +static inline int ad_sigma_delta_set_channel(struct ad_sigma_delta *sd,
> + unsigned int channel)
> +{
> + if (sd->info->set_channel)
> + return sd->info->set_channel(sd, channel);
> +
> + return 0;
> +}
> +
> +static inline int ad_sigma_delta_set_mode(struct ad_sigma_delta *sd,
> + unsigned int mode)
> +{
> + if (sd->info->set_mode)
> + return sd->info->set_mode(sd, mode);
> +
> + return 0;
> +}
> +
> +static inline int ad_sigma_delta_postprocess_sample(struct ad_sigma_delta *sd,
> + unsigned int raw_sample)
> +{
> + if (sd->info->postprocess_sample)
> + return sd->info->postprocess_sample(sd, raw_sample);
> +
> + return 0;
> +}
> +
> +void ad_sd_set_comm(struct ad_sigma_delta *sigma_delta, uint8_t comm);
> +int ad_sd_write_reg(struct ad_sigma_delta *sigma_delta, unsigned int reg,
> + unsigned int size, unsigned int val);
> +int ad_sd_read_reg(struct ad_sigma_delta *sigma_delta, unsigned int reg,
> + unsigned int size, unsigned int *val);
> +
> +int ad_sigma_delta_single_conversion(struct iio_dev *indio_dev,
> + const struct iio_chan_spec *chan, int *val);
> +int ad_sd_calibrate_all(struct ad_sigma_delta *sigma_delta,
> + const struct ad_sd_calib_data *cd, unsigned int n);
> +int ad_sd_init(struct ad_sigma_delta *sigma_delta, struct iio_dev *indio_dev,
> + struct spi_device *spi, const struct ad_sigma_delta_info *info);
> +
> +int ad_sd_setup_buffer_and_trigger(struct iio_dev *indio_dev);
> +void ad_sd_cleanup_buffer_and_trigger(struct iio_dev *indio_dev);
> +
> +int ad_sd_validate_trigger(struct iio_dev *indio_dev, struct iio_trigger *trig);
> +
> +#define __AD_SD_CHANNEL(_si, _channel1, _channel2, _address, _bits, \
> + _storagebits, _shift, _extend_name, _type) \
> + { \
> + .type = (_type), \
> + .differential = (_channel2 == -1 ? 0 : 1), \
> + .indexed = 1, \
> + .channel = (_channel1), \
> + .channel2 = (_channel2), \
> + .address = (_address), \
> + .extend_name = (_extend_name), \
> + .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
> + IIO_CHAN_INFO_SCALE_SHARED_BIT | \
> + IIO_CHAN_INFO_OFFSET_SEPARATE_BIT, \
> + .scan_index = (_si), \
> + .scan_type = { \
> + .sign = 'u', \
> + .realbits = (_bits), \
> + .storagebits = (_storagebits), \
> + .shift = (_shift), \
> + .endianness = IIO_BE, \
> + }, \
> + }
> +
> +#define AD_SD_DIFF_CHANNEL(_si, _channel1, _channel2, _address, _bits, \
> + _storagebits, _shift) \
> + __AD_SD_CHANNEL(_si, _channel1, _channel2, _address, _bits, \
> + _storagebits, _shift, NULL, IIO_VOLTAGE)
> +
> +#define AD_SD_SHORTED_CHANNEL(_si, _channel, _address, _bits, \
> + _storagebits, _shift) \
> + __AD_SD_CHANNEL(_si, _channel, _channel, _address, _bits, \
> + _storagebits, _shift, "shorted", IIO_VOLTAGE)
> +
> +#define AD_SD_CHANNEL(_si, _channel, _address, _bits, \
> + _storagebits, _shift) \
> + __AD_SD_CHANNEL(_si, _channel, -1, _address, _bits, \
> + _storagebits, _shift, NULL, IIO_VOLTAGE)
> +
> +#define AD_SD_TEMP_CHANNEL(_si, _address, _bits, _storagebits, _shift) \
> + __AD_SD_CHANNEL(_si, 0, -1, _address, _bits, \
> + _storagebits, _shift, NULL, IIO_TEMP)
> +
> +#define AD_SD_SUPPLY_CHANNEL(_si, _channel, _address, _bits, _storagebits, \
> + _shift) \
> + __AD_SD_CHANNEL(_si, _channel, -1, _address, _bits, \
> + _storagebits, _shift, "supply", IIO_VOLTAGE)
> +
> +#endif
>
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [PATCH 07/22] staging:iio:ad7793: Remove unused platform_data from device state struct
2012-08-14 19:39 ` Jonathan Cameron
@ 2012-08-14 20:19 ` Jonathan Cameron
2012-08-15 9:03 ` Lars-Peter Clausen
[not found] ` <502B6688.6000904@metafoo.de>
1 sibling, 1 reply; 37+ messages in thread
From: Jonathan Cameron @ 2012-08-14 20:19 UTC (permalink / raw)
To: Lars-Peter Clausen; +Cc: Jonathan Cameron, linux-iio, drivers
On 08/14/2012 08:39 PM, Jonathan Cameron wrote:
> On 08/10/2012 05:36 PM, Lars-Peter Clausen wrote:
>> The platform data for the device is only used from within the drivers probe
>> callback, so there is no need to keep it around in the devices state struct.
>>
>> While we are at it mark the platform data struct as const.
>>
There a couple of obvious bugs in this patch....
My plan with these is to first send a series to Greg with the
fixes in it (not including this which is merely a cleanup?)
Once that shows up in his trees I'll do a second pull request with
this + the sigma delta cleanups.
It is probably the cleanest approach and we aren't pressed for time
at the moment. To show what will be in there I will push out
a new branch to kernel.org shortly togreg-postfixes.
Lars-Peter, please verify that my fixup of this is correct
(all I've done is build tested it).
>> Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
>> ---
>> drivers/staging/iio/adc/ad7793.c | 14 ++++++--------
>> 1 file changed, 6 insertions(+), 8 deletions(-)
>>
>> diff --git a/drivers/staging/iio/adc/ad7793.c b/drivers/staging/iio/adc/ad7793.c
>> index 112e2b7..0ba598e 100644
>> --- a/drivers/staging/iio/adc/ad7793.c
>> +++ b/drivers/staging/iio/adc/ad7793.c
>> @@ -44,7 +44,6 @@ struct ad7793_state {
>> struct iio_trigger *trig;
>> const struct ad7793_chip_info *chip_info;
>> struct regulator *reg;
>> - struct ad7793_platform_data *pdata;
>> wait_queue_head_t wq_data_avail;
>> bool done;
>> bool irq_dis;
>> @@ -253,7 +252,8 @@ out:
>> return ret;
>> }
>>
>> -static int ad7793_setup(struct ad7793_state *st)
>> +static int ad7793_setup(struct ad7793_state *st
>> + const struct ad7793_platform_data *pdata)
> Really odd. There's a missing comma between the arguments here...
> I'll fixup.
>> {
>> int i, ret = -1;
>> unsigned long long scale_uv;
>> @@ -277,9 +277,9 @@ static int ad7793_setup(struct ad7793_state *st)
>> goto out;
>> }
>>
>> - st->mode = (st->pdata->mode & ~AD7793_MODE_SEL(-1)) |
>> + st->mode = (pdata->mode & ~AD7793_MODE_SEL(-1)) |
>> AD7793_MODE_SEL(AD7793_MODE_IDLE);
>> - st->conf = st->pdata->conf & ~AD7793_CONF_CHAN(-1);
>> + st->conf = pdata->conf & ~AD7793_CONF_CHAN(-1);
>>
>> ret = ad7793_write_reg(st, AD7793_REG_MODE, sizeof(st->mode), st->mode);
>> if (ret)
>> @@ -882,7 +882,7 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = {
>>
>> static int __devinit ad7793_probe(struct spi_device *spi)
>> {
>> - struct ad7793_platform_data *pdata = spi->dev.platform_data;
>> + const struct ad7793_platform_data *pdata = spi->dev.platform_data;
>> struct ad7793_state *st;
>> struct iio_dev *indio_dev;
>> int ret, voltage_uv = 0;
>> @@ -915,8 +915,6 @@ static int __devinit ad7793_probe(struct spi_device *spi)
>> st->chip_info =
>> &ad7793_chip_info_tbl[spi_get_device_id(spi)->driver_data];
>>
>> - st->pdata = pdata;
>> -
>> if (pdata && pdata->vref_mv)
>> st->int_vref_mv = pdata->vref_mv;
>> else if (voltage_uv)
>> @@ -944,7 +942,7 @@ static int __devinit ad7793_probe(struct spi_device *spi)
>> if (ret)
>> goto error_unreg_ring;
>>
>> - ret = ad7793_setup(st);
>> + ret = ad7793_setup(st, pdata);
>> if (ret)
>> goto error_remove_trigger;
>>
>>
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [PATCH 07/22] staging:iio:ad7793: Remove unused platform_data from device state struct
2012-08-14 20:19 ` Jonathan Cameron
@ 2012-08-15 9:03 ` Lars-Peter Clausen
2012-08-15 9:28 ` Jonathan Cameron
0 siblings, 1 reply; 37+ messages in thread
From: Lars-Peter Clausen @ 2012-08-15 9:03 UTC (permalink / raw)
To: Jonathan Cameron; +Cc: Jonathan Cameron, linux-iio, drivers
On 08/14/2012 10:19 PM, Jonathan Cameron wrote:
> On 08/14/2012 08:39 PM, Jonathan Cameron wrote:
>> On 08/10/2012 05:36 PM, Lars-Peter Clausen wrote:
>>> The platform data for the device is only used from within the drivers probe
>>> callback, so there is no need to keep it around in the devices state struct.
>>>
>>> While we are at it mark the platform data struct as const.
>>>
> There a couple of obvious bugs in this patch....
More than just the comma issue?
>
> My plan with these is to first send a series to Greg with the
> fixes in it (not including this which is merely a cleanup?)
> Once that shows up in his trees I'll do a second pull request with
> this + the sigma delta cleanups.
Sounds good.
> It is probably the cleanest approach and we aren't pressed for time
> at the moment. To show what will be in there I will push out
> a new branch to kernel.org shortly togreg-postfixes.
>
> Lars-Peter, please verify that my fixup of this is correct
> (all I've done is build tested it).
Will do, thanks.
>
>
>>> Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
>>> ---
>>> drivers/staging/iio/adc/ad7793.c | 14 ++++++--------
>>> 1 file changed, 6 insertions(+), 8 deletions(-)
>>>
>>> diff --git a/drivers/staging/iio/adc/ad7793.c b/drivers/staging/iio/adc/ad7793.c
>>> index 112e2b7..0ba598e 100644
>>> --- a/drivers/staging/iio/adc/ad7793.c
>>> +++ b/drivers/staging/iio/adc/ad7793.c
>>> @@ -44,7 +44,6 @@ struct ad7793_state {
>>> struct iio_trigger *trig;
>>> const struct ad7793_chip_info *chip_info;
>>> struct regulator *reg;
>>> - struct ad7793_platform_data *pdata;
>>> wait_queue_head_t wq_data_avail;
>>> bool done;
>>> bool irq_dis;
>>> @@ -253,7 +252,8 @@ out:
>>> return ret;
>>> }
>>>
>>> -static int ad7793_setup(struct ad7793_state *st)
>>> +static int ad7793_setup(struct ad7793_state *st
>>> + const struct ad7793_platform_data *pdata)
>> Really odd. There's a missing comma between the arguments here...
>> I'll fixup.
>>> {
>>> int i, ret = -1;
>>> unsigned long long scale_uv;
>>> @@ -277,9 +277,9 @@ static int ad7793_setup(struct ad7793_state *st)
>>> goto out;
>>> }
>>>
>>> - st->mode = (st->pdata->mode & ~AD7793_MODE_SEL(-1)) |
>>> + st->mode = (pdata->mode & ~AD7793_MODE_SEL(-1)) |
>>> AD7793_MODE_SEL(AD7793_MODE_IDLE);
>>> - st->conf = st->pdata->conf & ~AD7793_CONF_CHAN(-1);
>>> + st->conf = pdata->conf & ~AD7793_CONF_CHAN(-1);
>>>
>>> ret = ad7793_write_reg(st, AD7793_REG_MODE, sizeof(st->mode), st->mode);
>>> if (ret)
>>> @@ -882,7 +882,7 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = {
>>>
>>> static int __devinit ad7793_probe(struct spi_device *spi)
>>> {
>>> - struct ad7793_platform_data *pdata = spi->dev.platform_data;
>>> + const struct ad7793_platform_data *pdata = spi->dev.platform_data;
>>> struct ad7793_state *st;
>>> struct iio_dev *indio_dev;
>>> int ret, voltage_uv = 0;
>>> @@ -915,8 +915,6 @@ static int __devinit ad7793_probe(struct spi_device *spi)
>>> st->chip_info =
>>> &ad7793_chip_info_tbl[spi_get_device_id(spi)->driver_data];
>>>
>>> - st->pdata = pdata;
>>> -
>>> if (pdata && pdata->vref_mv)
>>> st->int_vref_mv = pdata->vref_mv;
>>> else if (voltage_uv)
>>> @@ -944,7 +942,7 @@ static int __devinit ad7793_probe(struct spi_device *spi)
>>> if (ret)
>>> goto error_unreg_ring;
>>>
>>> - ret = ad7793_setup(st);
>>> + ret = ad7793_setup(st, pdata);
>>> if (ret)
>>> goto error_remove_trigger;
>>>
>>>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-iio" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [PATCH 07/22] staging:iio:ad7793: Remove unused platform_data from device state struct
2012-08-15 9:03 ` Lars-Peter Clausen
@ 2012-08-15 9:28 ` Jonathan Cameron
0 siblings, 0 replies; 37+ messages in thread
From: Jonathan Cameron @ 2012-08-15 9:28 UTC (permalink / raw)
To: Lars-Peter Clausen; +Cc: Jonathan Cameron, Jonathan Cameron, linux-iio, drivers
On 15/08/12 10:03, Lars-Peter Clausen wrote:
> On 08/14/2012 10:19 PM, Jonathan Cameron wrote:
>> On 08/14/2012 08:39 PM, Jonathan Cameron wrote:
>>> On 08/10/2012 05:36 PM, Lars-Peter Clausen wrote:
>>>> The platform data for the device is only used from within the drivers probe
>>>> callback, so there is no need to keep it around in the devices state struct.
>>>>
>>>> While we are at it mark the platform data struct as const.
>>>>
>> There a couple of obvious bugs in this patch....
> More than just the comma issue?
Yup, you missed a few uses of pdata. Again in stuff that was removed by
later patches...
>
>> My plan with these is to first send a series to Greg with the
>> fixes in it (not including this which is merely a cleanup?)
>> Once that shows up in his trees I'll do a second pull request with
>> this + the sigma delta cleanups.
> Sounds good.
>
>> It is probably the cleanest approach and we aren't pressed for time
>> at the moment. To show what will be in there I will push out
>> a new branch to kernel.org shortly togreg-postfixes.
>>
>> Lars-Peter, please verify that my fixup of this is correct
>> (all I've done is build tested it).
> Will do, thanks.
>
>>
>>>> Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
>>>> ---
>>>> drivers/staging/iio/adc/ad7793.c | 14 ++++++--------
>>>> 1 file changed, 6 insertions(+), 8 deletions(-)
>>>>
>>>> diff --git a/drivers/staging/iio/adc/ad7793.c b/drivers/staging/iio/adc/ad7793.c
>>>> index 112e2b7..0ba598e 100644
>>>> --- a/drivers/staging/iio/adc/ad7793.c
>>>> +++ b/drivers/staging/iio/adc/ad7793.c
>>>> @@ -44,7 +44,6 @@ struct ad7793_state {
>>>> struct iio_trigger *trig;
>>>> const struct ad7793_chip_info *chip_info;
>>>> struct regulator *reg;
>>>> - struct ad7793_platform_data *pdata;
>>>> wait_queue_head_t wq_data_avail;
>>>> bool done;
>>>> bool irq_dis;
>>>> @@ -253,7 +252,8 @@ out:
>>>> return ret;
>>>> }
>>>>
>>>> -static int ad7793_setup(struct ad7793_state *st)
>>>> +static int ad7793_setup(struct ad7793_state *st
>>>> + const struct ad7793_platform_data *pdata)
>>> Really odd. There's a missing comma between the arguments here...
>>> I'll fixup.
>>>> {
>>>> int i, ret = -1;
>>>> unsigned long long scale_uv;
>>>> @@ -277,9 +277,9 @@ static int ad7793_setup(struct ad7793_state *st)
>>>> goto out;
>>>> }
>>>>
>>>> - st->mode = (st->pdata->mode & ~AD7793_MODE_SEL(-1)) |
>>>> + st->mode = (pdata->mode & ~AD7793_MODE_SEL(-1)) |
>>>> AD7793_MODE_SEL(AD7793_MODE_IDLE);
>>>> - st->conf = st->pdata->conf & ~AD7793_CONF_CHAN(-1);
>>>> + st->conf = pdata->conf & ~AD7793_CONF_CHAN(-1);
>>>>
>>>> ret = ad7793_write_reg(st, AD7793_REG_MODE, sizeof(st->mode), st->mode);
>>>> if (ret)
>>>> @@ -882,7 +882,7 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = {
>>>>
>>>> static int __devinit ad7793_probe(struct spi_device *spi)
>>>> {
>>>> - struct ad7793_platform_data *pdata = spi->dev.platform_data;
>>>> + const struct ad7793_platform_data *pdata = spi->dev.platform_data;
>>>> struct ad7793_state *st;
>>>> struct iio_dev *indio_dev;
>>>> int ret, voltage_uv = 0;
>>>> @@ -915,8 +915,6 @@ static int __devinit ad7793_probe(struct spi_device *spi)
>>>> st->chip_info =
>>>> &ad7793_chip_info_tbl[spi_get_device_id(spi)->driver_data];
>>>>
>>>> - st->pdata = pdata;
>>>> -
>>>> if (pdata && pdata->vref_mv)
>>>> st->int_vref_mv = pdata->vref_mv;
>>>> else if (voltage_uv)
>>>> @@ -944,7 +942,7 @@ static int __devinit ad7793_probe(struct spi_device *spi)
>>>> if (ret)
>>>> goto error_unreg_ring;
>>>>
>>>> - ret = ad7793_setup(st);
>>>> + ret = ad7793_setup(st, pdata);
>>>> if (ret)
>>>> goto error_remove_trigger;
>>>>
>>>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-iio" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [PATCH 19/22] staging:iio:ad7192: Use common Sigma Delta library
2012-08-10 16:36 ` [PATCH 19/22] staging:iio:ad7192: " Lars-Peter Clausen
@ 2012-08-27 17:07 ` Jonathan Cameron
2012-09-03 8:13 ` Lars-Peter Clausen
0 siblings, 1 reply; 37+ messages in thread
From: Jonathan Cameron @ 2012-08-27 17:07 UTC (permalink / raw)
To: Lars-Peter Clausen; +Cc: Jonathan Cameron, linux-iio, drivers
On 08/10/2012 05:36 PM, Lars-Peter Clausen wrote:
> Convert the ad7192 driver to make use of the new common code for devices from
> the Analog Devices Sigma Delta family.
Hi Lars-Peter.
Was just applying these to my togreg branch and ran a few build tests with sparse.
issue in this and ad7793 came up.
drivers/staging/iio/adc/ad7793.c:91:21: warning: incorrect type in initializer (incompatible argument 2 (different
signedness))
drivers/staging/iio/adc/ad7793.c:91:21: expected int ( *set_mode )( ... )
drivers/staging/iio/adc/ad7793.c:91:21: got int ( static [toplevel] *<noident> )( ... )
Now this is because set_mode takes and integer argument here, but is defined to
take an enum.
Why not just take the enum directly?
I'm guessing this is a left over from a cleanup that didn't
quite get everywhere. Will convert them over to the enum argument before
pushing them out, but would like you to take a quick glance at them...
Change given inline below.
>
> Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
> ---
> drivers/staging/iio/adc/Kconfig | 3 +-
> drivers/staging/iio/adc/ad7192.c | 507 +++++---------------------------------
> 2 files changed, 61 insertions(+), 449 deletions(-)
>
> diff --git a/drivers/staging/iio/adc/Kconfig b/drivers/staging/iio/adc/Kconfig
> index 05dea3f..9525308 100644
> --- a/drivers/staging/iio/adc/Kconfig
> +++ b/drivers/staging/iio/adc/Kconfig
> @@ -131,8 +131,7 @@ config AD7816
> config AD7192
> tristate "Analog Devices AD7190 AD7192 AD7195 ADC driver"
> depends on SPI
> - select IIO_BUFFER
> - select IIO_TRIGGERED_BUFFER
> + select AD_SIGMA_DELTA
> help
> Say yes here to build support for Analog Devices AD7190,
> AD7192 or AD7195 SPI analog to digital converters (ADC).
> diff --git a/drivers/staging/iio/adc/ad7192.c b/drivers/staging/iio/adc/ad7192.c
> index cdb4fc4..34a7dee 100644
> --- a/drivers/staging/iio/adc/ad7192.c
> +++ b/drivers/staging/iio/adc/ad7192.c
> @@ -23,6 +23,7 @@
> #include <linux/iio/trigger.h>
> #include <linux/iio/trigger_consumer.h>
> #include <linux/iio/triggered_buffer.h>
> +#include <linux/iio/adc/ad_sigma_delta.h>
>
> #include "ad7192.h"
>
> @@ -57,6 +58,7 @@
>
> /* Mode Register Bit Designations (AD7192_REG_MODE) */
> #define AD7192_MODE_SEL(x) (((x) & 0x7) << 21) /* Operation Mode Select */
> +#define AD7192_MODE_SEL_MASK (0x7 << 21) /* Operation Mode Select Mask */
> #define AD7192_MODE_DAT_STA (1 << 20) /* Status Register transmission */
> #define AD7192_MODE_CLKSRC(x) (((x) & 0x3) << 18) /* Clock Source Select */
> #define AD7192_MODE_SINC3 (1 << 15) /* SINC3 Filter Select */
> @@ -91,7 +93,8 @@
>
> #define AD7192_CONF_CHOP (1 << 23) /* CHOP enable */
> #define AD7192_CONF_REFSEL (1 << 20) /* REFIN1/REFIN2 Reference Select */
> -#define AD7192_CONF_CHAN(x) (((x) & 0xFF) << 8) /* Channel select */
> +#define AD7192_CONF_CHAN(x) (((1 << (x)) & 0xFF) << 8) /* Channel select */
> +#define AD7192_CONF_CHAN_MASK (0xFF << 8) /* Channel select mask */
> #define AD7192_CONF_BURN (1 << 7) /* Burnout current enable */
> #define AD7192_CONF_REFDET (1 << 6) /* Reference detect enable */
> #define AD7192_CONF_BUF (1 << 4) /* Buffered Mode Enable */
> @@ -133,12 +136,7 @@
> */
>
> struct ad7192_state {
> - struct spi_device *spi;
> - struct iio_trigger *trig;
> struct regulator *reg;
> - wait_queue_head_t wq_data_avail;
> - bool done;
> - bool irq_dis;
> u16 int_vref_mv;
> u32 mclk;
> u32 f_order;
> @@ -147,178 +145,44 @@ struct ad7192_state {
> u32 scale_avail[8][2];
> u8 gpocon;
> u8 devid;
> - /*
> - * DMA (thus cache coherency maintenance) requires the
> - * transfer buffers to live in their own cache lines.
> - */
> - u8 data[4] ____cacheline_aligned;
> -};
> -
> -static int __ad7192_write_reg(struct ad7192_state *st, bool locked,
> - bool cs_change, unsigned char reg,
> - unsigned size, unsigned val)
> -{
> - u8 *data = st->data;
> - struct spi_transfer t = {
> - .tx_buf = data,
> - .len = size + 1,
> - .cs_change = cs_change,
> - };
> - struct spi_message m;
> -
> - data[0] = AD7192_COMM_WRITE | AD7192_COMM_ADDR(reg);
> -
> - switch (size) {
> - case 3:
> - data[1] = val >> 16;
> - data[2] = val >> 8;
> - data[3] = val;
> - break;
> - case 2:
> - data[1] = val >> 8;
> - data[2] = val;
> - break;
> - case 1:
> - data[1] = val;
> - break;
> - default:
> - return -EINVAL;
> - }
>
> - spi_message_init(&m);
> - spi_message_add_tail(&t, &m);
> -
> - if (locked)
> - return spi_sync_locked(st->spi, &m);
> - else
> - return spi_sync(st->spi, &m);
> -}
> + struct ad_sigma_delta sd;
> +};
>
> -static int ad7192_write_reg(struct ad7192_state *st,
> - unsigned reg, unsigned size, unsigned val)
> +static struct ad7192_state *ad_sigma_delta_to_ad7192(struct ad_sigma_delta *sd)
> {
> - return __ad7192_write_reg(st, false, false, reg, size, val);
> + return container_of(sd, struct ad7192_state, sd);
> }
>
> -static int __ad7192_read_reg(struct ad7192_state *st, bool locked,
> - bool cs_change, unsigned char reg,
> - int *val, unsigned size)
> +static int ad7192_set_channel(struct ad_sigma_delta *sd, unsigned int channel)
> {
> - u8 *data = st->data;
> - int ret;
> - struct spi_transfer t[] = {
> - {
> - .tx_buf = data,
> - .len = 1,
> - }, {
> - .rx_buf = data,
> - .len = size,
> - .cs_change = cs_change,
> - },
> - };
> - struct spi_message m;
> -
> - data[0] = AD7192_COMM_READ | AD7192_COMM_ADDR(reg);
> -
> - spi_message_init(&m);
> - spi_message_add_tail(&t[0], &m);
> - spi_message_add_tail(&t[1], &m);
> -
> - if (locked)
> - ret = spi_sync_locked(st->spi, &m);
> - else
> - ret = spi_sync(st->spi, &m);
> + struct ad7192_state *st = ad_sigma_delta_to_ad7192(sd);
>
> - if (ret < 0)
> - return ret;
> + st->conf &= ~AD7192_CONF_CHAN_MASK;
> + st->conf |= AD7192_CONF_CHAN(channel);
>
> - switch (size) {
> - case 3:
> - *val = data[0] << 16 | data[1] << 8 | data[2];
> - break;
> - case 2:
> - *val = data[0] << 8 | data[1];
> - break;
> - case 1:
> - *val = data[0];
> - break;
> - default:
> - return -EINVAL;
> - }
> -
> - return 0;
> + return ad_sd_write_reg(&st->sd, AD7192_REG_CONF, 3, st->conf);
> }
>
> -static int ad7192_read_reg(struct ad7192_state *st,
> - unsigned reg, int *val, unsigned size)
Change is here,
static int ad7793_set_mode(struct ad_sigma_delta *sd,
enum ad_sigma_delta_mode mode)
> +static int ad7192_set_mode(struct ad_sigma_delta *sd, unsigned int mode)
> {
> - return __ad7192_read_reg(st, 0, 0, reg, val, size);
> -}
> -
> -static int ad7192_read(struct ad7192_state *st, unsigned ch,
> - unsigned len, int *val)
> -{
> - int ret;
> - st->conf = (st->conf & ~AD7192_CONF_CHAN(-1)) |
> - AD7192_CONF_CHAN(1 << ch);
> - st->mode = (st->mode & ~AD7192_MODE_SEL(-1)) |
> - AD7192_MODE_SEL(AD7192_MODE_SINGLE);
> -
> - ad7192_write_reg(st, AD7192_REG_CONF, 3, st->conf);
> + struct ad7192_state *st = ad_sigma_delta_to_ad7192(sd);
>
> - spi_bus_lock(st->spi->master);
> - st->done = false;
> + st->mode &= ~AD7192_MODE_SEL_MASK;
> + st->mode |= AD7192_MODE_SEL(mode);
>
> - ret = __ad7192_write_reg(st, 1, 1, AD7192_REG_MODE, 3, st->mode);
> - if (ret < 0)
> - goto out;
> -
> - st->irq_dis = false;
> - enable_irq(st->spi->irq);
> - wait_event_interruptible(st->wq_data_avail, st->done);
> -
> - ret = __ad7192_read_reg(st, 1, 0, AD7192_REG_DATA, val, len);
> -out:
> - spi_bus_unlock(st->spi->master);
> -
> - return ret;
> + return ad_sd_write_reg(&st->sd, AD7192_REG_MODE, 3, st->mode);
> }
>
> -static int ad7192_calibrate(struct ad7192_state *st, unsigned mode, unsigned ch)
> -{
> - int ret;
> -
> - st->conf = (st->conf & ~AD7192_CONF_CHAN(-1)) |
> - AD7192_CONF_CHAN(1 << ch);
> - st->mode = (st->mode & ~AD7192_MODE_SEL(-1)) | AD7192_MODE_SEL(mode);
> -
> - ad7192_write_reg(st, AD7192_REG_CONF, 3, st->conf);
> -
> - spi_bus_lock(st->spi->master);
> - st->done = false;
> -
> - ret = __ad7192_write_reg(st, 1, 1, AD7192_REG_MODE, 3,
> - (st->devid != ID_AD7195) ?
> - st->mode | AD7192_MODE_CLKDIV :
> - st->mode);
> - if (ret < 0)
> - goto out;
> -
> - st->irq_dis = false;
> - enable_irq(st->spi->irq);
> - wait_event_interruptible(st->wq_data_avail, st->done);
> -
> - st->mode = (st->mode & ~AD7192_MODE_SEL(-1)) |
> - AD7192_MODE_SEL(AD7192_MODE_IDLE);
> -
> - ret = __ad7192_write_reg(st, 1, 0, AD7192_REG_MODE, 3, st->mode);
> -out:
> - spi_bus_unlock(st->spi->master);
> -
> - return ret;
> -}
> +static const struct ad_sigma_delta_info ad7192_sigma_delta_info = {
> + .set_channel = ad7192_set_channel,
> + .set_mode = ad7192_set_mode,
> + .has_registers = true,
> + .addr_shift = 3,
> + .read_mask = BIT(6),
> +};
>
> -static const u8 ad7192_calib_arr[8][2] = {
> +static const struct ad_sd_calib_data ad7192_calib_arr[8] = {
> {AD7192_MODE_CAL_INT_ZERO, AD7192_CH_AIN1},
> {AD7192_MODE_CAL_INT_FULL, AD7192_CH_AIN1},
> {AD7192_MODE_CAL_INT_ZERO, AD7192_CH_AIN2},
> @@ -331,45 +195,34 @@ static const u8 ad7192_calib_arr[8][2] = {
>
> static int ad7192_calibrate_all(struct ad7192_state *st)
> {
> - int i, ret;
> -
> - for (i = 0; i < ARRAY_SIZE(ad7192_calib_arr); i++) {
> - ret = ad7192_calibrate(st, ad7192_calib_arr[i][0],
> - ad7192_calib_arr[i][1]);
> - if (ret)
> - goto out;
> - }
> -
> - return 0;
> -out:
> - dev_err(&st->spi->dev, "Calibration failed\n");
> - return ret;
> + return ad_sd_calibrate_all(&st->sd, ad7192_calib_arr,
> + ARRAY_SIZE(ad7192_calib_arr));
> }
>
> static int ad7192_setup(struct ad7192_state *st,
> const struct ad7192_platform_data *pdata)
> {
> - struct iio_dev *indio_dev = spi_get_drvdata(st->spi);
> + struct iio_dev *indio_dev = spi_get_drvdata(st->sd.spi);
> unsigned long long scale_uv;
> int i, ret, id;
> u8 ones[6];
>
> /* reset the serial interface */
> memset(&ones, 0xFF, 6);
> - ret = spi_write(st->spi, &ones, 6);
> + ret = spi_write(st->sd.spi, &ones, 6);
> if (ret < 0)
> goto out;
> msleep(1); /* Wait for at least 500us */
>
> /* write/read test for device presence */
> - ret = ad7192_read_reg(st, AD7192_REG_ID, &id, 1);
> + ret = ad_sd_read_reg(&st->sd, AD7192_REG_ID, 1, &id);
> if (ret)
> goto out;
>
> id &= AD7192_ID_MASK;
>
> if (id != st->devid)
> - dev_warn(&st->spi->dev, "device ID query failed (0x%X)\n", id);
> + dev_warn(&st->sd.spi->dev, "device ID query failed (0x%X)\n", id);
>
> switch (pdata->clock_source_sel) {
> case AD7192_CLK_EXT_MCLK1_2:
> @@ -422,11 +275,11 @@ static int ad7192_setup(struct ad7192_state *st,
> if (pdata->burnout_curr_en)
> st->conf |= AD7192_CONF_BURN;
>
> - ret = ad7192_write_reg(st, AD7192_REG_MODE, 3, st->mode);
> + ret = ad_sd_write_reg(&st->sd, AD7192_REG_MODE, 3, st->mode);
> if (ret)
> goto out;
>
> - ret = ad7192_write_reg(st, AD7192_REG_CONF, 3, st->conf);
> + ret = ad_sd_write_reg(&st->sd, AD7192_REG_CONF, 3, st->conf);
> if (ret)
> goto out;
>
> @@ -447,181 +300,10 @@ static int ad7192_setup(struct ad7192_state *st,
>
> return 0;
> out:
> - dev_err(&st->spi->dev, "setup failed\n");
> + dev_err(&st->sd.spi->dev, "setup failed\n");
> return ret;
> }
>
> -static int ad7192_ring_preenable(struct iio_dev *indio_dev)
> -{
> - struct ad7192_state *st = iio_priv(indio_dev);
> - unsigned channel;
> - int ret;
> -
> - if (bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength))
> - return -EINVAL;
> -
> - ret = iio_sw_buffer_preenable(indio_dev);
> - if (ret < 0)
> - return ret;
> -
> - channel = find_first_bit(indio_dev->active_scan_mask,
> - indio_dev->masklength);
> -
> - st->mode = (st->mode & ~AD7192_MODE_SEL(-1)) |
> - AD7192_MODE_SEL(AD7192_MODE_CONT);
> - st->conf = (st->conf & ~AD7192_CONF_CHAN(-1)) |
> - AD7192_CONF_CHAN(1 << indio_dev->channels[channel].address);
> -
> - ad7192_write_reg(st, AD7192_REG_CONF, 3, st->conf);
> -
> - spi_bus_lock(st->spi->master);
> - __ad7192_write_reg(st, 1, 1, AD7192_REG_MODE, 3, st->mode);
> -
> - st->irq_dis = false;
> - enable_irq(st->spi->irq);
> -
> - return 0;
> -}
> -
> -static int ad7192_ring_postdisable(struct iio_dev *indio_dev)
> -{
> - struct ad7192_state *st = iio_priv(indio_dev);
> -
> - st->mode = (st->mode & ~AD7192_MODE_SEL(-1)) |
> - AD7192_MODE_SEL(AD7192_MODE_IDLE);
> -
> - st->done = false;
> - wait_event_interruptible(st->wq_data_avail, st->done);
> -
> - if (!st->irq_dis)
> - disable_irq_nosync(st->spi->irq);
> -
> - __ad7192_write_reg(st, 1, 0, AD7192_REG_MODE, 3, st->mode);
> -
> - return spi_bus_unlock(st->spi->master);
> -}
> -
> -/**
> - * ad7192_trigger_handler() bh of trigger launched polling to ring buffer
> - **/
> -static irqreturn_t ad7192_trigger_handler(int irq, void *p)
> -{
> - struct iio_poll_func *pf = p;
> - struct iio_dev *indio_dev = pf->indio_dev;
> - struct iio_buffer *ring = indio_dev->buffer;
> - struct ad7192_state *st = iio_priv(indio_dev);
> - s64 dat64[2];
> - s32 *dat32 = (s32 *)dat64;
> -
> - if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength))
> - __ad7192_read_reg(st, 1, 1, AD7192_REG_DATA,
> - dat32,
> - indio_dev->channels[0].scan_type.realbits/8);
> -
> - /* Guaranteed to be aligned with 8 byte boundary */
> - if (indio_dev->scan_timestamp)
> - dat64[1] = pf->timestamp;
> -
> - ring->access->store_to(ring, (u8 *)dat64, pf->timestamp);
> -
> - iio_trigger_notify_done(indio_dev->trig);
> - st->irq_dis = false;
> - enable_irq(st->spi->irq);
> -
> - return IRQ_HANDLED;
> -}
> -
> -static const struct iio_buffer_setup_ops ad7192_ring_setup_ops = {
> - .preenable = &ad7192_ring_preenable,
> - .postenable = &iio_triggered_buffer_postenable,
> - .predisable = &iio_triggered_buffer_predisable,
> - .postdisable = &ad7192_ring_postdisable,
> - .validate_scan_mask = &iio_validate_scan_mask_onehot,
> -};
> -
> -static int ad7192_register_ring_funcs_and_init(struct iio_dev *indio_dev)
> -{
> - return iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,
> - &ad7192_trigger_handler, &ad7192_ring_setup_ops);
> -}
> -
> -static void ad7192_ring_cleanup(struct iio_dev *indio_dev)
> -{
> - iio_triggered_buffer_cleanup(indio_dev);
> -}
> -
> -/**
> - * ad7192_data_rdy_trig_poll() the event handler for the data rdy trig
> - **/
> -static irqreturn_t ad7192_data_rdy_trig_poll(int irq, void *private)
> -{
> - struct ad7192_state *st = iio_priv(private);
> -
> - st->done = true;
> - wake_up_interruptible(&st->wq_data_avail);
> - disable_irq_nosync(irq);
> - st->irq_dis = true;
> - iio_trigger_poll(st->trig, iio_get_time_ns());
> -
> - return IRQ_HANDLED;
> -}
> -
> -static struct iio_trigger_ops ad7192_trigger_ops = {
> - .owner = THIS_MODULE,
> -};
> -
> -static int ad7192_probe_trigger(struct iio_dev *indio_dev)
> -{
> - struct ad7192_state *st = iio_priv(indio_dev);
> - int ret;
> -
> - st->trig = iio_trigger_alloc("%s-dev%d",
> - spi_get_device_id(st->spi)->name,
> - indio_dev->id);
> - if (st->trig == NULL) {
> - ret = -ENOMEM;
> - goto error_ret;
> - }
> - st->trig->ops = &ad7192_trigger_ops;
> - ret = request_irq(st->spi->irq,
> - ad7192_data_rdy_trig_poll,
> - IRQF_TRIGGER_LOW,
> - spi_get_device_id(st->spi)->name,
> - indio_dev);
> - if (ret)
> - goto error_free_trig;
> -
> - disable_irq_nosync(st->spi->irq);
> - st->irq_dis = true;
> - st->trig->dev.parent = &st->spi->dev;
> - st->trig->private_data = indio_dev;
> -
> - ret = iio_trigger_register(st->trig);
> -
> - /* select default trigger */
> - indio_dev->trig = st->trig;
> - if (ret)
> - goto error_free_irq;
> -
> - return 0;
> -
> -error_free_irq:
> - free_irq(st->spi->irq, indio_dev);
> -error_free_trig:
> - iio_trigger_free(st->trig);
> -error_ret:
> - return ret;
> -}
> -
> -static void ad7192_remove_trigger(struct iio_dev *indio_dev)
> -{
> - struct ad7192_state *st = iio_priv(indio_dev);
> -
> - iio_trigger_unregister(st->trig);
> - free_irq(st->spi->irq, indio_dev);
> - iio_trigger_free(st->trig);
> -}
> -
> static ssize_t ad7192_read_frequency(struct device *dev,
> struct device_attribute *attr,
> char *buf)
> @@ -661,7 +343,7 @@ static ssize_t ad7192_write_frequency(struct device *dev,
>
> st->mode &= ~AD7192_MODE_RATE(-1);
> st->mode |= AD7192_MODE_RATE(div);
> - ad7192_write_reg(st, AD7192_REG_MODE, 3, st->mode);
> + ad_sd_write_reg(&st->sd, AD7192_REG_MODE, 3, st->mode);
>
> out:
> mutex_unlock(&indio_dev->mlock);
> @@ -673,7 +355,6 @@ static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
> ad7192_read_frequency,
> ad7192_write_frequency);
>
> -
> static ssize_t ad7192_show_scale_available(struct device *dev,
> struct device_attribute *attr, char *buf)
> {
> @@ -745,7 +426,7 @@ static ssize_t ad7192_set(struct device *dev,
> else
> st->gpocon &= ~AD7192_GPOCON_BPDSW;
>
> - ad7192_write_reg(st, AD7192_REG_GPOCON, 1, st->gpocon);
> + ad_sd_write_reg(&st->sd, AD7192_REG_GPOCON, 1, st->gpocon);
> break;
> case AD7192_REG_MODE:
> if (val)
> @@ -753,7 +434,7 @@ static ssize_t ad7192_set(struct device *dev,
> else
> st->mode &= ~AD7192_MODE_ACX;
>
> - ad7192_write_reg(st, AD7192_REG_MODE, 3, st->mode);
> + ad_sd_write_reg(&st->sd, AD7192_REG_MODE, 3, st->mode);
> break;
> default:
> ret = -EINVAL;
> @@ -809,27 +490,11 @@ static int ad7192_read_raw(struct iio_dev *indio_dev,
> long m)
> {
> struct ad7192_state *st = iio_priv(indio_dev);
> - int ret, smpl = 0;
> bool unipolar = !!(st->conf & AD7192_CONF_UNIPOLAR);
>
> switch (m) {
> case IIO_CHAN_INFO_RAW:
> - mutex_lock(&indio_dev->mlock);
> - if (iio_buffer_enabled(indio_dev))
> - ret = -EBUSY;
> - else
> - ret = ad7192_read(st, chan->address,
> - chan->scan_type.realbits / 8, &smpl);
> - mutex_unlock(&indio_dev->mlock);
> -
> - if (ret < 0)
> - return ret;
> -
> - *val = (smpl >> chan->scan_type.shift) &
> - ((1 << (chan->scan_type.realbits)) - 1);
> -
> - return IIO_VAL_INT;
> -
> + return ad_sigma_delta_single_conversion(indio_dev, chan, val);
> case IIO_CHAN_INFO_SCALE:
> switch (chan->type) {
> case IIO_VOLTAGE:
> @@ -880,16 +545,16 @@ static int ad7192_write_raw(struct iio_dev *indio_dev,
> ret = -EINVAL;
> for (i = 0; i < ARRAY_SIZE(st->scale_avail); i++)
> if (val2 == st->scale_avail[i][1]) {
> + ret = 0;
> tmp = st->conf;
> st->conf &= ~AD7192_CONF_GAIN(-1);
> st->conf |= AD7192_CONF_GAIN(i);
> -
> - if (tmp != st->conf) {
> - ad7192_write_reg(st, AD7192_REG_CONF,
> - 3, st->conf);
> - ad7192_calibrate_all(st);
> - }
> - ret = 0;
> + if (tmp == st->conf)
> + break;
> + ad_sd_write_reg(&st->sd, AD7192_REG_CONF,
> + 3, st->conf);
> + ad7192_calibrate_all(st);
> + break;
> }
> break;
> default:
> @@ -901,15 +566,6 @@ static int ad7192_write_raw(struct iio_dev *indio_dev,
> return ret;
> }
>
> -static int ad7192_validate_trigger(struct iio_dev *indio_dev,
> - struct iio_trigger *trig)
> -{
> - if (indio_dev->trig != trig)
> - return -EINVAL;
> -
> - return 0;
> -}
> -
> static int ad7192_write_raw_get_fmt(struct iio_dev *indio_dev,
> struct iio_chan_spec const *chan,
> long mask)
> @@ -922,7 +578,7 @@ static const struct iio_info ad7192_info = {
> .write_raw = &ad7192_write_raw,
> .write_raw_get_fmt = &ad7192_write_raw_get_fmt,
> .attrs = &ad7192_attribute_group,
> - .validate_trigger = ad7192_validate_trigger,
> + .validate_trigger = ad_sd_validate_trigger,
> .driver_module = THIS_MODULE,
> };
>
> @@ -931,54 +587,19 @@ static const struct iio_info ad7195_info = {
> .write_raw = &ad7192_write_raw,
> .write_raw_get_fmt = &ad7192_write_raw_get_fmt,
> .attrs = &ad7195_attribute_group,
> - .validate_trigger = ad7192_validate_trigger,
> + .validate_trigger = ad_sd_validate_trigger,
> .driver_module = THIS_MODULE,
> };
>
> -#define AD7192_CHAN_DIFF(_chan, _chan2, _name, _address, _si) \
> - { .type = IIO_VOLTAGE, \
> - .differential = 1, \
> - .indexed = 1, \
> - .extend_name = _name, \
> - .channel = _chan, \
> - .channel2 = _chan2, \
> - .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
> - IIO_CHAN_INFO_SCALE_SHARED_BIT | \
> - IIO_CHAN_INFO_OFFSET_SHARED_BIT, \
> - .address = _address, \
> - .scan_index = _si, \
> - .scan_type = IIO_ST('u', 24, 32, 0)}
> -
> -#define AD7192_CHAN(_chan, _address, _si) \
> - { .type = IIO_VOLTAGE, \
> - .indexed = 1, \
> - .channel = _chan, \
> - .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
> - IIO_CHAN_INFO_SCALE_SHARED_BIT | \
> - IIO_CHAN_INFO_OFFSET_SHARED_BIT, \
> - .address = _address, \
> - .scan_index = _si, \
> - .scan_type = IIO_ST('u', 24, 32, 0)}
> -
> -#define AD7192_CHAN_TEMP(_chan, _address, _si) \
> - { .type = IIO_TEMP, \
> - .indexed = 1, \
> - .channel = _chan, \
> - .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
> - IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \
> - .address = _address, \
> - .scan_index = _si, \
> - .scan_type = IIO_ST('u', 24, 32, 0)}
> -
> static const struct iio_chan_spec ad7192_channels[] = {
> - AD7192_CHAN_DIFF(1, 2, NULL, AD7192_CH_AIN1P_AIN2M, 0),
> - AD7192_CHAN_DIFF(3, 4, NULL, AD7192_CH_AIN3P_AIN4M, 1),
> - AD7192_CHAN_TEMP(0, AD7192_CH_TEMP, 2),
> - AD7192_CHAN_DIFF(2, 2, "shorted", AD7192_CH_AIN2P_AIN2M, 3),
> - AD7192_CHAN(1, AD7192_CH_AIN1, 4),
> - AD7192_CHAN(2, AD7192_CH_AIN2, 5),
> - AD7192_CHAN(3, AD7192_CH_AIN3, 6),
> - AD7192_CHAN(4, AD7192_CH_AIN4, 7),
> + AD_SD_DIFF_CHANNEL(0, 1, 2, AD7192_CH_AIN1P_AIN2M, 24, 32, 0),
> + AD_SD_DIFF_CHANNEL(1, 3, 4, AD7192_CH_AIN3P_AIN4M, 24, 32, 0),
> + AD_SD_TEMP_CHANNEL(2, AD7192_CH_TEMP, 24, 32, 0),
> + AD_SD_SHORTED_CHANNEL(3, 2, AD7192_CH_AIN2P_AIN2M, 24, 32, 0),
> + AD_SD_CHANNEL(4, 1, AD7192_CH_AIN1, 24, 32, 0),
> + AD_SD_CHANNEL(5, 2, AD7192_CH_AIN2, 24, 32, 0),
> + AD_SD_CHANNEL(6, 3, AD7192_CH_AIN3, 24, 32, 0),
> + AD_SD_CHANNEL(7, 4, AD7192_CH_AIN4, 24, 32, 0),
> IIO_CHAN_SOFT_TIMESTAMP(8),
> };
>
> @@ -1022,7 +643,6 @@ static int __devinit ad7192_probe(struct spi_device *spi)
> dev_warn(&spi->dev, "reference voltage undefined\n");
>
> spi_set_drvdata(spi, indio_dev);
> - st->spi = spi;
> st->devid = spi_get_device_id(spi)->driver_data;
> indio_dev->dev.parent = &spi->dev;
> indio_dev->name = spi_get_device_id(spi)->name;
> @@ -1034,16 +654,12 @@ static int __devinit ad7192_probe(struct spi_device *spi)
> else
> indio_dev->info = &ad7192_info;
>
> - init_waitqueue_head(&st->wq_data_avail);
> + ad_sd_init(&st->sd, indio_dev, spi, &ad7192_sigma_delta_info);
>
> - ret = ad7192_register_ring_funcs_and_init(indio_dev);
> + ret = ad_sd_setup_buffer_and_trigger(indio_dev);
> if (ret)
> goto error_disable_reg;
>
> - ret = ad7192_probe_trigger(indio_dev);
> - if (ret)
> - goto error_ring_cleanup;
> -
> ret = ad7192_setup(st, pdata);
> if (ret)
> goto error_remove_trigger;
> @@ -1054,9 +670,7 @@ static int __devinit ad7192_probe(struct spi_device *spi)
> return 0;
>
> error_remove_trigger:
> - ad7192_remove_trigger(indio_dev);
> -error_ring_cleanup:
> - ad7192_ring_cleanup(indio_dev);
> + ad_sd_cleanup_buffer_and_trigger(indio_dev);
> error_disable_reg:
> if (!IS_ERR(st->reg))
> regulator_disable(st->reg);
> @@ -1075,8 +689,7 @@ static int ad7192_remove(struct spi_device *spi)
> struct ad7192_state *st = iio_priv(indio_dev);
>
> iio_device_unregister(indio_dev);
> - ad7192_remove_trigger(indio_dev);
> - ad7192_ring_cleanup(indio_dev);
> + ad_sd_cleanup_buffer_and_trigger(indio_dev);
>
> if (!IS_ERR(st->reg)) {
> regulator_disable(st->reg);
>
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [PATCH 19/22] staging:iio:ad7192: Use common Sigma Delta library
2012-08-27 17:07 ` Jonathan Cameron
@ 2012-09-03 8:13 ` Lars-Peter Clausen
0 siblings, 0 replies; 37+ messages in thread
From: Lars-Peter Clausen @ 2012-09-03 8:13 UTC (permalink / raw)
To: Jonathan Cameron; +Cc: Jonathan Cameron, linux-iio, drivers
On 08/27/2012 07:07 PM, Jonathan Cameron wrote:
> On 08/10/2012 05:36 PM, Lars-Peter Clausen wrote:
>> Convert the ad7192 driver to make use of the new common code for devices from
>> the Analog Devices Sigma Delta family.
>
> Hi Lars-Peter.
>
> Was just applying these to my togreg branch and ran a few build tests with sparse.
> issue in this and ad7793 came up.
>
> drivers/staging/iio/adc/ad7793.c:91:21: warning: incorrect type in initializer (incompatible argument 2 (different
> signedness))
> drivers/staging/iio/adc/ad7793.c:91:21: expected int ( *set_mode )( ... )
> drivers/staging/iio/adc/ad7793.c:91:21: got int ( static [toplevel] *<noident> )( ... )
>
>
> Now this is because set_mode takes and integer argument here, but is defined to
> take an enum.
>
> Why not just take the enum directly?
>
> I'm guessing this is a left over from a cleanup that didn't
> quite get everywhere. Will convert them over to the enum argument before
> pushing them out, but would like you to take a quick glance at them...
>
> Change given inline below.
>>
>>[...]
>>
>> -static int ad7192_read_reg(struct ad7192_state *st,
>> - unsigned reg, int *val, unsigned size)
> Change is here,
>
> static int ad7793_set_mode(struct ad_sigma_delta *sd,
> enum ad_sigma_delta_mode mode)
Yes, looks good, except for the part number ;) Both patch 18 (ad7793) and 19
(ad7192) have the same issue.
Thanks.
>
>> +static int ad7192_set_mode(struct ad_sigma_delta *sd, unsigned int mode)
>> {
>> - return __ad7192_read_reg(st, 0, 0, reg, val, size);
>> -}
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [PATCH 07/22] staging:iio:ad7793: Remove unused platform_data from device state struct
[not found] ` <502B6688.6000904@metafoo.de>
@ 2012-09-03 16:39 ` Lars-Peter Clausen
2012-09-03 20:09 ` Jonathan Cameron
0 siblings, 1 reply; 37+ messages in thread
From: Lars-Peter Clausen @ 2012-09-03 16:39 UTC (permalink / raw)
To: Jonathan Cameron; +Cc: Jonathan Cameron, linux-iio, drivers
On 08/15/2012 11:06 AM, Lars-Peter Clausen wrote:
> On 08/14/2012 09:39 PM, Jonathan Cameron wrote:
>> On 08/10/2012 05:36 PM, Lars-Peter Clausen wrote:
>>> The platform data for the device is only used from within the drivers probe
>>> callback, so there is no need to keep it around in the devices state struct.
>>>
>>> While we are at it mark the platform data struct as const.
>>>
>>> Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
>>> ---
>>> drivers/staging/iio/adc/ad7793.c | 14 ++++++--------
>>> 1 file changed, 6 insertions(+), 8 deletions(-)
>>>
>>> diff --git a/drivers/staging/iio/adc/ad7793.c b/drivers/staging/iio/adc/ad7793.c
>>> index 112e2b7..0ba598e 100644
>>> --- a/drivers/staging/iio/adc/ad7793.c
>>> +++ b/drivers/staging/iio/adc/ad7793.c
>>> @@ -44,7 +44,6 @@ struct ad7793_state {
>>> struct iio_trigger *trig;
>>> const struct ad7793_chip_info *chip_info;
>>> struct regulator *reg;
>>> - struct ad7793_platform_data *pdata;
>>> wait_queue_head_t wq_data_avail;
>>> bool done;
>>> bool irq_dis;
>>> @@ -253,7 +252,8 @@ out:
>>> return ret;
>>> }
>>>
>>> -static int ad7793_setup(struct ad7793_state *st)
>>> +static int ad7793_setup(struct ad7793_state *st
>>> + const struct ad7793_platform_data *pdata)
>> Really odd. There's a missing comma between the arguments here...
>> I'll fixup.
>
> I think this happened during a rebase and I never spotted it because it was
> fixed up in a later commit. Reminds me to run a built tests on each individual
> patch and not just the whole series together.
Ok, to avoid such mistakes in the future I've come up with the following one
liner shell script. I though it might be worth sharing in case others find
this useful as well.
#!/bin/sh
EDITOR="sed -i 's/^\(pick .*\)$/\1\nexec make/'" git rebase -p -i $1
Pass it a commit id and it will run `make` for each commit in the range of
the passed commit up to HEAD. If make fails it will stop at the current commit.
E.g.
`./git-compiletest HEAD~10`
- Lars
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [PATCH 07/22] staging:iio:ad7793: Remove unused platform_data from device state struct
2012-09-03 16:39 ` Lars-Peter Clausen
@ 2012-09-03 20:09 ` Jonathan Cameron
0 siblings, 0 replies; 37+ messages in thread
From: Jonathan Cameron @ 2012-09-03 20:09 UTC (permalink / raw)
To: Lars-Peter Clausen; +Cc: Jonathan Cameron, linux-iio, drivers
On 09/03/2012 05:39 PM, Lars-Peter Clausen wrote:
> On 08/15/2012 11:06 AM, Lars-Peter Clausen wrote:
>> On 08/14/2012 09:39 PM, Jonathan Cameron wrote:
>>> On 08/10/2012 05:36 PM, Lars-Peter Clausen wrote:
>>>> The platform data for the device is only used from within the drivers probe
>>>> callback, so there is no need to keep it around in the devices state struct.
>>>>
>>>> While we are at it mark the platform data struct as const.
>>>>
>>>> Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
>>>> ---
>>>> drivers/staging/iio/adc/ad7793.c | 14 ++++++--------
>>>> 1 file changed, 6 insertions(+), 8 deletions(-)
>>>>
>>>> diff --git a/drivers/staging/iio/adc/ad7793.c b/drivers/staging/iio/adc/ad7793.c
>>>> index 112e2b7..0ba598e 100644
>>>> --- a/drivers/staging/iio/adc/ad7793.c
>>>> +++ b/drivers/staging/iio/adc/ad7793.c
>>>> @@ -44,7 +44,6 @@ struct ad7793_state {
>>>> struct iio_trigger *trig;
>>>> const struct ad7793_chip_info *chip_info;
>>>> struct regulator *reg;
>>>> - struct ad7793_platform_data *pdata;
>>>> wait_queue_head_t wq_data_avail;
>>>> bool done;
>>>> bool irq_dis;
>>>> @@ -253,7 +252,8 @@ out:
>>>> return ret;
>>>> }
>>>>
>>>> -static int ad7793_setup(struct ad7793_state *st)
>>>> +static int ad7793_setup(struct ad7793_state *st
>>>> + const struct ad7793_platform_data *pdata)
>>> Really odd. There's a missing comma between the arguments here...
>>> I'll fixup.
>>
>> I think this happened during a rebase and I never spotted it because it was
>> fixed up in a later commit. Reminds me to run a built tests on each individual
>> patch and not just the whole series together.
>
> Ok, to avoid such mistakes in the future I've come up with the following one
> liner shell script. I though it might be worth sharing in case others find
> this useful as well.
>
> #!/bin/sh
> EDITOR="sed -i 's/^\(pick .*\)$/\1\nexec make/'" git rebase -p -i $1
>
>
> Pass it a commit id and it will run `make` for each commit in the range of
> the passed commit up to HEAD. If make fails it will stop at the current commit.
>
> E.g.
>
> `./git-compiletest HEAD~10`
>
Nice little script
All but 22 of this series are now merged and pull requests sent.
Thanks,
Jonathan
^ permalink raw reply [flat|nested] 37+ messages in thread
end of thread, other threads:[~2012-09-03 20:09 UTC | newest]
Thread overview: 37+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-08-10 16:36 [PATCH 01/22] staging:iio:ad7793: Add missing break in switch statement Lars-Peter Clausen
2012-08-10 16:36 ` [PATCH 02/22] staging:iio:ad7793: Mark channels as unsigned Lars-Peter Clausen
2012-08-10 16:36 ` [PATCH 03/22] staging:iio:ad7793: Report channel offset Lars-Peter Clausen
2012-08-10 16:36 ` [PATCH 04/22] staging:iio:ad7793: Fix temperature scale and offset Lars-Peter Clausen
2012-08-10 16:36 ` [PATCH 05/22] staging:iio:ad7793: Follow new IIO naming spec Lars-Peter Clausen
2012-08-10 16:36 ` [PATCH 06/22] staging:iio:ad7793: Fix internal reference value Lars-Peter Clausen
2012-08-10 16:36 ` [PATCH 07/22] staging:iio:ad7793: Remove unused platform_data from device state struct Lars-Peter Clausen
2012-08-14 19:39 ` Jonathan Cameron
2012-08-14 20:19 ` Jonathan Cameron
2012-08-15 9:03 ` Lars-Peter Clausen
2012-08-15 9:28 ` Jonathan Cameron
[not found] ` <502B6688.6000904@metafoo.de>
2012-09-03 16:39 ` Lars-Peter Clausen
2012-09-03 20:09 ` Jonathan Cameron
2012-08-10 16:36 ` [PATCH 08/22] staging:iio:ad7192: Add missing break in switch statement Lars-Peter Clausen
2012-08-10 16:36 ` [PATCH 09/22] staging:iio:ad7192: Fix setting ACX Lars-Peter Clausen
2012-08-10 16:36 ` [PATCH 10/22] staging:iio:ad7192: Mark channels as unsigned Lars-Peter Clausen
2012-08-10 16:36 ` [PATCH 11/22] staging:iio:ad7192: Report channel offset Lars-Peter Clausen
2012-08-10 16:36 ` [PATCH 12/22] staging:iio:ad7192: Report offset and scale for temperature channel Lars-Peter Clausen
2012-08-10 16:36 ` [PATCH 13/22] staging:iio:ad7192: Remove unused platform_data from device state struct Lars-Peter Clausen
2012-08-10 16:36 ` [PATCH 14/22] staging:iio:ad7780: Mark channels as unsigned Lars-Peter Clausen
2012-08-10 16:36 ` [PATCH 15/22] iio: Introduce iio_device_{set,get}_drvdata() Lars-Peter Clausen
2012-08-10 16:36 ` [PATCH 16/22] iio:adc: Add common code for ADI Sigma Delta devices Lars-Peter Clausen
2012-08-14 12:03 ` Jonathan Cameron
2012-08-14 20:19 ` Jonathan Cameron
2012-08-10 16:36 ` [PATCH 17/22] staging:iio:ad7780: Use common Sigma Delta library Lars-Peter Clausen
2012-08-14 12:05 ` Jonathan Cameron
2012-08-10 16:36 ` [PATCH 18/22] staging:iio:ad7793: " Lars-Peter Clausen
2012-08-10 16:36 ` [PATCH 19/22] staging:iio:ad7192: " Lars-Peter Clausen
2012-08-27 17:07 ` Jonathan Cameron
2012-09-03 8:13 ` Lars-Peter Clausen
2012-08-10 16:36 ` [PATCH 20/22] staging:iio:ad7793: Add support for ad7794/ad7795 Lars-Peter Clausen
2012-08-10 16:36 ` [PATCH 21/22] staging:iio:ad7793: Add ad7785 support Lars-Peter Clausen
2012-08-10 16:36 ` [PATCH 22/22] staging:iio:adc: Add AD7791 driver Lars-Peter Clausen
2012-08-11 8:41 ` Peter Meerwald
2012-08-11 17:37 ` Lars-Peter Clausen
2012-08-13 13:12 ` Lars-Peter Clausen
2012-08-14 20:18 ` Jonathan Cameron
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).